diff options
| author | Egor Yusov <egor.yusov@gmail.com> | 2018-05-21 16:01:53 +0000 |
|---|---|---|
| committer | Egor Yusov <egor.yusov@gmail.com> | 2018-05-21 16:01:53 +0000 |
| commit | 06d2c110aa58d0fbc771bd142e1c795cfc39ca0f (patch) | |
| tree | efd074c41d3ffb4b95cc78e999b65e4897e1c5b4 /Graphics/GraphicsEngineVulkan | |
| parent | Updated static resource intialization in Vk (diff) | |
| download | DiligentCore-06d2c110aa58d0fbc771bd142e1c795cfc39ca0f.tar.gz DiligentCore-06d2c110aa58d0fbc771bd142e1c795cfc39ca0f.zip | |
Implemented shader resource transitioning to proper states in Vulkan
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
17 files changed, 317 insertions, 261 deletions
diff --git a/Graphics/GraphicsEngineVulkan/include/BufferVkImpl.h b/Graphics/GraphicsEngineVulkan/include/BufferVkImpl.h index e9423b2d..ba14efaf 100644 --- a/Graphics/GraphicsEngineVulkan/include/BufferVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/BufferVkImpl.h @@ -102,9 +102,11 @@ public: //VERIFY(DataStartByteOffset == 0, "0 offset expected"); return VkBuffer; } -/* - virtual void SetVkResourceState(Vk_RESOURCE_STATES state)override final{ SetState(state); } + virtual void SetAccessFlags(VkAccessFlags AccessFlags )override final{ m_AccessFlags = AccessFlags; } + VkAccessFlags GetAccessFlags()const{return m_AccessFlags;} + +/* Vk_GPU_VIRTUAL_ADDRESS GetGPUAddress(Uint32 ContextId) { if(m_Desc.Usage == USAGE_DYNAMIC) @@ -126,8 +128,9 @@ private: virtual void CreateViewInternal( const struct BufferViewDesc &ViewDesc, IBufferView **ppView, bool bIsDefaultView )override; VulkanUtilities::BufferViewWrapper CreateView(struct BufferViewDesc &ViewDesc); - /* DescriptorHeapAllocation m_CBVDescriptorAllocation; + VkAccessFlags m_AccessFlags = 0; + /* #ifdef _DEBUG std::vector< std::pair<MAP_TYPE, Uint32>, STDAllocatorRawMem<std::pair<MAP_TYPE, Uint32>> > m_DbgMapType; #endif diff --git a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h index 774cc37a..5b9891e7 100644 --- a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h @@ -86,8 +86,12 @@ public: virtual void ExecuteCommandList(class ICommandList *pCommandList)override final; + void TransitionImageLayout(class TextureVkImpl &TextureVk, VkImageLayout NewLayout); virtual void TransitionImageLayout(ITexture *pTexture, VkImageLayout NewLayout)override final; + void BufferMemoryBarrier(class BufferVkImpl &BufferVk, VkAccessFlags NewAccessFlags); + virtual void BufferMemoryBarrier(IBuffer *pBuffer, VkAccessFlags NewAccessFlags)override final; + void AddWaitSemaphore(VkSemaphore Semaphore, VkPipelineStageFlags WaitDstStageMask) { m_WaitSemaphores.push_back(Semaphore); diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineLayout.h b/Graphics/GraphicsEngineVulkan/include/PipelineLayout.h index 64f31c1a..1e82aa2e 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineLayout.h +++ b/Graphics/GraphicsEngineVulkan/include/PipelineLayout.h @@ -31,6 +31,7 @@ #include "ShaderResourceLayoutVk.h" #include "VulkanUtilities/VulkanObjectWrappers.h" #include "VulkanUtilities/VulkanLogicalDevice.h" +#include "VulkanUtilities/VulkanCommandBuffer.h" namespace Diligent { @@ -59,6 +60,8 @@ public: Uint32& OffsetInCache, std::vector<uint32_t>& SPIRV); + // This method should be thread-safe as it does not modify any object state + #if 0 // This method should be thread-safe as it does not modify any object state void (PipelineLayout::*CommitDescriptorHandles)(RenderDeviceVkImpl *pRenderDeviceVk, @@ -70,15 +73,8 @@ public: ShaderResourceCacheVk& ResourceCache, class CommandContext &Ctx, bool IsCompute)const = nullptr; - - void TransitionResources(ShaderResourceCacheVk& ResourceCache, - class CommandContext &Ctx)const; - - void CommitRootViews(ShaderResourceCacheVk& ResourceCache, - class CommandContext &Ctx, - bool IsCompute, - Uint32 ContextId)const; #endif + Uint32 GetTotalDescriptors(SHADER_VARIABLE_TYPE VarType)const { VERIFY_EXPR(VarType >= 0 && VarType < SHADER_VARIABLE_TYPE_NUM_TYPES); @@ -162,21 +158,6 @@ private: IMemoryAllocator &m_MemAllocator; DescriptorSetLayoutManager m_LayoutMgr; - -#if 0 - // Commits descriptor handles for static and mutable variables - template<bool PerformResourceTransitions> - void CommitDescriptorHandlesInternal_SM(RenderDeviceVkImpl *pRenderDeviceVk, - ShaderResourceCacheVk& ResourceCache, - class CommandContext &Ctx, - bool IsCompute)const; - template<bool PerformResourceTransitions> - // Commits descriptor handles for static, mutable, and dynamic variables - void CommitDescriptorHandlesInternal_SMD(RenderDeviceVkImpl *pRenderDeviceVk, - ShaderResourceCacheVk& ResourceCache, - class CommandContext &Ctx, - bool IsCompute)const; -#endif }; } diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h index 865a3540..3b7166e2 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h @@ -64,10 +64,10 @@ public: virtual VkPipeline GetVkPipeline()const override final { return m_Pipeline; } - ShaderResourceCacheVk* CommitAndTransitionShaderResources(IShaderResourceBinding* pShaderResourceBinding, - VulkanUtilities::VulkanCommandBuffer& CmdBuff, - bool CommitResources, - bool TransitionResources)const; + ShaderResourceCacheVk* CommitAndTransitionShaderResources(IShaderResourceBinding* pShaderResourceBinding, + DeviceContextVkImpl* pCtxVkImpl, + bool CommitResources, + bool TransitionResources)const; const PipelineLayout& GetPipelineLayout()const{return m_PipelineLayout;} @@ -78,8 +78,6 @@ public: return *m_pShaderResourceLayouts[ShaderInd]; } - //bool dbgContainsShaderResources()const; - IMemoryAllocator& GetResourceCacheDataAllocator(){return m_ResourceCacheDataAllocator;} IMemoryAllocator& GetShaderResourceLayoutDataAllocator(Uint32 ActiveShaderInd) { diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h index 5ad52522..02f347bb 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h @@ -57,10 +57,13 @@ // Dynamic resources are not VkDescriptorSet #include "DescriptorPoolManager.h" +#include "SPIRVShaderResources.h" namespace Diligent { +class DeviceContextVkImpl; + class ShaderResourceCacheVk { public: @@ -80,10 +83,12 @@ public: ~ShaderResourceCacheVk(); - void Initialize(IMemoryAllocator &MemAllocator, Uint32 NumSets, Uint32 SetSizes[]); + void InitializeSets(IMemoryAllocator &MemAllocator, Uint32 NumSets, Uint32 SetSizes[]); + void InitializeResources(Uint32 Set, Uint32 Offset, Uint32 ArraySize, SPIRVShaderResourceAttribs::ResourceType Type); struct Resource { + const SPIRVShaderResourceAttribs::ResourceType Type; RefCntAutoPtr<IDeviceObject> pObject; }; @@ -134,15 +139,19 @@ public: DbgCacheContentType DbgGetContentType()const{return m_DbgContentType;} #endif + template<bool VerifyOnly> + void TransitionResources(DeviceContextVkImpl *pCtxVkImpl); + private: ShaderResourceCacheVk (const ShaderResourceCacheVk&) = delete; ShaderResourceCacheVk (ShaderResourceCacheVk&&) = delete; ShaderResourceCacheVk& operator = (const ShaderResourceCacheVk&) = delete; ShaderResourceCacheVk& operator = (ShaderResourceCacheVk&&) = delete; - IMemoryAllocator* m_pAllocator = nullptr; - void* m_pMemory = nullptr; - Uint32 m_NumSets = 0; + IMemoryAllocator* m_pAllocator = nullptr; + void* m_pMemory = nullptr; + Uint32 m_NumSets = 0; + Uint32 m_TotalResources = 0; #ifdef _DEBUG // Only for debug purposes: indicates what types of resources are stored in the cache diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h index 4bb3b1b7..93dd41b0 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h @@ -278,6 +278,8 @@ public: return m_NumResources[VarType]; } + void InitializeResourcesInCache(); + private: void InitVariablesHashMap(); diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.h b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.h index 54bf8302..43e41dd5 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.h +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.h @@ -284,6 +284,31 @@ namespace VulkanUtilities TransitionImageLayout(m_VkCmdBuffer, Image, OldLayout, NewLayout, SubresRange, SrcStages, DestStages); } + + static void BufferMemoryBarrier(VkCommandBuffer CmdBuffer, + VkBuffer Buffer, + VkAccessFlags srcAccessMask, + VkAccessFlags dstAccessMask, + VkPipelineStageFlags SrcStages, + VkPipelineStageFlags DestStages); + + void BufferMemoryBarrier(VkBuffer Buffer, + VkAccessFlags srcAccessMask, + VkAccessFlags dstAccessMask, + VkPipelineStageFlags SrcStages = 0, + VkPipelineStageFlags DestStages = 0) + { + VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE); + if(m_State.RenderPass != VK_NULL_HANDLE) + { + // Image layout transitions within a render pass execute + // dependencies between attachments + EndRenderPass(); + } + BufferMemoryBarrier(m_VkCmdBuffer, Buffer, srcAccessMask, dstAccessMask, SrcStages, DestStages); + } + + void FlushBarriers(); void SetVkCmdBuffer(VkCommandBuffer VkCmdBuffer) diff --git a/Graphics/GraphicsEngineVulkan/interface/BufferVk.h b/Graphics/GraphicsEngineVulkan/interface/BufferVk.h index 767d1a9b..8f2bc4d1 100644 --- a/Graphics/GraphicsEngineVulkan/interface/BufferVk.h +++ b/Graphics/GraphicsEngineVulkan/interface/BufferVk.h @@ -44,10 +44,10 @@ public: /// Returns a vulkan buffer handle virtual VkBuffer GetVkBuffer() = 0; - /// Sets the buffer usage state + /// Sets vulkan access flags - /// \param [in] state - D3D12 resource state to be set for this buffer - //virtual void SetD3D12ResourceState(D3D12_RESOURCE_STATES state) = 0; + /// \param [in] AccessFlags - Vulkan access flags to be set for this buffer + virtual void SetAccessFlags(VkAccessFlags AccessFlags) = 0; }; } diff --git a/Graphics/GraphicsEngineVulkan/interface/DeviceContextVk.h b/Graphics/GraphicsEngineVulkan/interface/DeviceContextVk.h index 50ec9d75..cb8eb676 100644 --- a/Graphics/GraphicsEngineVulkan/interface/DeviceContextVk.h +++ b/Graphics/GraphicsEngineVulkan/interface/DeviceContextVk.h @@ -46,11 +46,11 @@ public: /// \param [in] NewLayout - Vulkan image layout this texture to transition to virtual void TransitionImageLayout(ITexture *pTexture, VkImageLayout NewLayout) = 0; - /// Transitions internal D3D12 buffer object to a specified state + /// Transitions internal vulkan buffer object to a specified state /// \param [in] pBuffer - Buffer to transition - /// \param [in] State - D3D12 resource state this buffer to transition to - //virtual void TransitionBufferState(IBuffer *pBuffer, D3D12_RESOURCE_STATES State) = 0; + /// \param [in] NewAccessFlags - Access flags to set for the buffer + virtual void BufferMemoryBarrier(IBuffer *pBuffer, VkAccessFlags NewAccessFlags) = 0; }; } diff --git a/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp index 3878c5cf..8bd36c3e 100644 --- a/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp @@ -154,9 +154,11 @@ BufferVkImpl :: BufferVkImpl(IReferenceCounters *pRefCounters, bool bInitializeBuffer = (BuffData.pData != nullptr && BuffData.DataSize > 0); //if(bInitializeBuffer) // m_UsageState = Vk_RESOURCE_STATE_COPY_DEST; - - if( bInitializeBuffer ) + + if( bInitializeBuffer ) { + m_AccessFlags = VK_ACCESS_TRANSFER_WRITE_BIT; + VkBufferCreateInfo VkStaginBuffCI = VkBuffCI; VkStaginBuffCI.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; @@ -248,6 +250,10 @@ BufferVkImpl :: BufferVkImpl(IReferenceCounters *pRefCounters, pRenderDeviceVk->SafeReleaseVkObject(std::move(StagingBuffer)); pRenderDeviceVk->SafeReleaseVkObject(std::move(StagingBufferMemory)); } + else + { + m_AccessFlags = 0; + } //if (m_Desc.BindFlags & BIND_UNIFORM_BUFFER) //{ diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index e5281833..a6ed69de 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -203,10 +203,8 @@ namespace Diligent if (!DeviceContextBase::CommitShaderResources<PipelineStateVkImpl>(pShaderResourceBinding, Flags, 0 /*Dummy*/)) return; - EnsureVkCmdBuffer(); auto *pPipelineStateVk = m_pPipelineState.RawPtr<PipelineStateVkImpl>(); - - m_pCommittedResourceCache = pPipelineStateVk->CommitAndTransitionShaderResources(pShaderResourceBinding, m_CommandBuffer, true, (Flags & COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES)!=0); + m_pCommittedResourceCache = pPipelineStateVk->CommitAndTransitionShaderResources(pShaderResourceBinding, this, true, (Flags & COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES)!=0); } void DeviceContextVkImpl::SetStencilRef(Uint32 StencilRef) @@ -1142,46 +1140,62 @@ namespace Diligent #endif } - void DeviceContextVkImpl::TransitionImageLayout(ITexture *pTexture, VkImageLayout NewLayout) { VERIFY_EXPR(pTexture != nullptr); auto pTextureVk = ValidatedCast<TextureVkImpl>(pTexture); - if(pTextureVk->GetLayout() != NewLayout) + if (pTextureVk->GetLayout() != NewLayout) { - EnsureVkCmdBuffer(); + TransitionImageLayout(*pTextureVk, NewLayout); + } + } + + void DeviceContextVkImpl::TransitionImageLayout(TextureVkImpl &TextureVk, VkImageLayout NewLayout) + { + VERIFY(TextureVk.GetLayout() != NewLayout, "The texture is already transitioned to correct layout"); + EnsureVkCmdBuffer(); - auto vkImg = pTextureVk->GetVkImage(); - const auto& TexDesc = pTextureVk->GetDesc(); - auto Fmt = TexDesc.Format; - const auto& FmtAttribs = GetTextureFormatAttribs(Fmt); - VkImageSubresourceRange SubresRange; - if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH) - SubresRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - else if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL) - { - // If image has a depth / stencil format with both depth and stencil components, then the - // aspectMask member of subresourceRange must include both VK_IMAGE_ASPECT_DEPTH_BIT and - // VK_IMAGE_ASPECT_STENCIL_BIT (6.7.3) - SubresRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - } - else - SubresRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - SubresRange.baseArrayLayer = 0; - SubresRange.layerCount = VK_REMAINING_ARRAY_LAYERS; - SubresRange.baseMipLevel = 0; - SubresRange.levelCount = VK_REMAINING_MIP_LEVELS; - m_CommandBuffer.TransitionImageLayout(vkImg, pTextureVk->GetLayout(), NewLayout, SubresRange); - pTextureVk->SetLayout(NewLayout); + auto vkImg = TextureVk.GetVkImage(); + const auto& TexDesc = TextureVk.GetDesc(); + auto Fmt = TexDesc.Format; + const auto& FmtAttribs = GetTextureFormatAttribs(Fmt); + VkImageSubresourceRange SubresRange; + if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH) + SubresRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + else if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL) + { + // If image has a depth / stencil format with both depth and stencil components, then the + // aspectMask member of subresourceRange must include both VK_IMAGE_ASPECT_DEPTH_BIT and + // VK_IMAGE_ASPECT_STENCIL_BIT (6.7.3) + SubresRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; } + else + SubresRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + SubresRange.baseArrayLayer = 0; + SubresRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + SubresRange.baseMipLevel = 0; + SubresRange.levelCount = VK_REMAINING_MIP_LEVELS; + m_CommandBuffer.TransitionImageLayout(vkImg, TextureVk.GetLayout(), NewLayout, SubresRange); + TextureVk.SetLayout(NewLayout); } -#if 0 - void DeviceContextVkImpl::TransitionBufferState(IBuffer *pBuffer, Vk_RESOURCE_STATES State) + void DeviceContextVkImpl::BufferMemoryBarrier(IBuffer *pBuffer, VkAccessFlags NewAccessFlags) { VERIFY_EXPR(pBuffer != nullptr); - auto *pCmdCtx = RequestCmdContext(); - pCmdCtx->TransitionResource(ValidatedCast<IBufferVk>(pBuffer), State); + auto pBuffVk = ValidatedCast<BufferVkImpl>(pBuffer); + if (pBuffVk->GetAccessFlags() != NewAccessFlags) + { + BufferMemoryBarrier(*pBuffVk, NewAccessFlags); + } + } + + void DeviceContextVkImpl::BufferMemoryBarrier(BufferVkImpl &BufferVk, VkAccessFlags NewAccessFlags) + { + VERIFY(BufferVk.GetAccessFlags() != NewAccessFlags, "The buffer already has requested access flags"); + EnsureVkCmdBuffer(); + + auto vkBuff = BufferVk.GetVkBuffer(); + m_CommandBuffer.BufferMemoryBarrier(vkBuff, BufferVk.GetAccessFlags(), NewAccessFlags); + BufferVk.SetAccessFlags(NewAccessFlags); } -#endif } diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp index 4e8ad773..f427b7a0 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp @@ -542,7 +542,9 @@ void PipelineLayout::InitResourceCache(RenderDeviceVkImpl *pDeviceVkImpl, Shader SetSizes[DynamicSet.SetIndex] = DynamicSet.TotalDescriptors; } - ResourceCache.Initialize(CacheMemAllocator, NumSets, SetSizes.data()); + // This call only initializes descriptor sets (ShaderResourceCacheVk::DescriptorSet) in the resource cache + // Resources are initialized when shader resource layout objects are created and attached to the cache + ResourceCache.InitializeSets(CacheMemAllocator, NumSets, SetSizes.data()); if (StaticAndMutSet.SetIndex >= 0) { ResourceCache.GetDescriptorSet(StaticAndMutSet.SetIndex).AssignDescriptorSetAllocation(std::move(SetAllocation)); @@ -654,149 +656,7 @@ void PipelineLayout::InitResourceCache(RenderDeviceVkImpl *pDeviceVkImpl, Shader } #if 0 -const Vk_RESOURCE_STATES Vk_RESOURCE_STATE_SHADER_RESOURCE = Vk_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | Vk_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; -__forceinline -void TransitionResource(CommandContext &Ctx, - ShaderResourceCacheVk::Resource &Res, - Vk_DESCRIPTOR_RANGE_TYPE RangeType) -{ - switch (Res.Type) - { - case CachedResourceType::CBV: - { - VERIFY(RangeType == Vk_DESCRIPTOR_RANGE_TYPE_CBV, "Unexpected descriptor range type"); - // Not using QueryInterface() for the sake of efficiency - auto *pBuffToTransition = Res.pObject.RawPtr<BufferVkImpl>(); - if( !pBuffToTransition->CheckAllStates(Vk_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER) ) - Ctx.TransitionResource(pBuffToTransition, Vk_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER ); - } - break; - - case CachedResourceType::BufSRV: - { - VERIFY(RangeType == Vk_DESCRIPTOR_RANGE_TYPE_SRV, "Unexpected descriptor range type"); - auto *pBuffViewVk = Res.pObject.RawPtr<BufferViewVkImpl>(); - auto *pBuffToTransition = ValidatedCast<BufferVkImpl>(pBuffViewVk->GetBuffer()); - if( !pBuffToTransition->CheckAllStates(Vk_RESOURCE_STATE_SHADER_RESOURCE) ) - Ctx.TransitionResource(pBuffToTransition, Vk_RESOURCE_STATE_SHADER_RESOURCE ); - } - break; - - case CachedResourceType::BufUAV: - { - VERIFY(RangeType == Vk_DESCRIPTOR_RANGE_TYPE_UAV, "Unexpected descriptor range type"); - auto *pBuffViewVk = Res.pObject.RawPtr<BufferViewVkImpl>(); - auto *pBuffToTransition = ValidatedCast<BufferVkImpl>(pBuffViewVk->GetBuffer()); - if( !pBuffToTransition->CheckAllStates(Vk_RESOURCE_STATE_UNORDERED_ACCESS) ) - Ctx.TransitionResource(pBuffToTransition, Vk_RESOURCE_STATE_UNORDERED_ACCESS ); - } - break; - - case CachedResourceType::TexSRV: - { - VERIFY(RangeType == Vk_DESCRIPTOR_RANGE_TYPE_SRV, "Unexpected descriptor range type"); - auto *pTexViewVk = Res.pObject.RawPtr<TextureViewVkImpl>(); - auto *pTexToTransition = ValidatedCast<TextureVkImpl>(pTexViewVk->GetTexture()); - if( !pTexToTransition->CheckAllStates(Vk_RESOURCE_STATE_SHADER_RESOURCE) ) - Ctx.TransitionResource(pTexToTransition, Vk_RESOURCE_STATE_SHADER_RESOURCE ); - } - break; - - case CachedResourceType::TexUAV: - { - VERIFY(RangeType == Vk_DESCRIPTOR_RANGE_TYPE_UAV, "Unexpected descriptor range type"); - auto *pTexViewVk = Res.pObject.RawPtr<TextureViewVkImpl>(); - auto *pTexToTransition = ValidatedCast<TextureVkImpl>(pTexViewVk->GetTexture()); - if( !pTexToTransition->CheckAllStates(Vk_RESOURCE_STATE_UNORDERED_ACCESS) ) - Ctx.TransitionResource(pTexToTransition, Vk_RESOURCE_STATE_UNORDERED_ACCESS ); - } - break; - - case CachedResourceType::Sampler: - VERIFY(RangeType == Vk_DESCRIPTOR_RANGE_TYPE_SAMPLER, "Unexpected descriptor range type"); - break; - - default: - // Resource not bound - VERIFY(Res.Type == CachedResourceType::Unknown, "Unexpected resource type"); - VERIFY(Res.pObject == nullptr && Res.CPUDescriptorHandle.ptr == 0, "Bound resource is unexpected"); - } -} - - -#ifdef _DEBUG -void DbgVerifyResourceState(ShaderResourceCacheVk::Resource &Res, - Vk_DESCRIPTOR_RANGE_TYPE RangeType) -{ - switch (Res.Type) - { - case CachedResourceType::CBV: - { - VERIFY(RangeType == Vk_DESCRIPTOR_RANGE_TYPE_CBV, "Unexpected descriptor range type"); - // Not using QueryInterface() for the sake of efficiency - auto *pBuffToTransition = Res.pObject.RawPtr<BufferVkImpl>(); - auto State = pBuffToTransition->GetState(); - if( (State & Vk_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER) != Vk_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER ) - LOG_ERROR_MESSAGE("Resource \"", pBuffToTransition->GetDesc().Name, "\" is not in Vk_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER state. Did you forget to call TransitionShaderResources() or specify COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES flag in a call to CommitShaderResources()?" ); - } - break; - - case CachedResourceType::BufSRV: - { - VERIFY(RangeType == Vk_DESCRIPTOR_RANGE_TYPE_SRV, "Unexpected descriptor range type"); - auto *pBuffViewVk = Res.pObject.RawPtr<BufferViewVkImpl>(); - auto *pBuffToTransition = ValidatedCast<BufferVkImpl>(pBuffViewVk->GetBuffer()); - auto State = pBuffToTransition->GetState(); - if( (State & Vk_RESOURCE_STATE_SHADER_RESOURCE) != Vk_RESOURCE_STATE_SHADER_RESOURCE ) - LOG_ERROR_MESSAGE("Resource \"", pBuffToTransition->GetDesc().Name, "\" is not in correct state. Did you forget to call TransitionShaderResources() or specify COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES flag in a call to CommitShaderResources()?" ); - } - break; - - case CachedResourceType::BufUAV: - { - VERIFY(RangeType == Vk_DESCRIPTOR_RANGE_TYPE_UAV, "Unexpected descriptor range type"); - auto *pBuffViewVk = Res.pObject.RawPtr<BufferViewVkImpl>(); - auto *pBuffToTransition = ValidatedCast<BufferVkImpl>(pBuffViewVk->GetBuffer()); - auto State = pBuffToTransition->GetState(); - if( (State & Vk_RESOURCE_STATE_UNORDERED_ACCESS) != Vk_RESOURCE_STATE_UNORDERED_ACCESS ) - LOG_ERROR_MESSAGE("Resource \"", pBuffToTransition->GetDesc().Name, "\" is not in Vk_RESOURCE_STATE_UNORDERED_ACCESS state. Did you forget to call TransitionShaderResources() or specify COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES flag in a call to CommitShaderResources()?" ); - } - break; - - case CachedResourceType::TexSRV: - { - VERIFY(RangeType == Vk_DESCRIPTOR_RANGE_TYPE_SRV, "Unexpected descriptor range type"); - auto *pTexViewVk = Res.pObject.RawPtr<TextureViewVkImpl>(); - auto *pTexToTransition = ValidatedCast<TextureVkImpl>(pTexViewVk->GetTexture()); - auto State = pTexToTransition->GetState(); - if( (State & Vk_RESOURCE_STATE_SHADER_RESOURCE) != Vk_RESOURCE_STATE_SHADER_RESOURCE ) - LOG_ERROR_MESSAGE("Resource \"", pTexToTransition->GetDesc().Name, "\" is not in correct state. Did you forget to call TransitionShaderResources() or specify COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES flag in a call to CommitShaderResources()?" ); - } - break; - - case CachedResourceType::TexUAV: - { - VERIFY(RangeType == Vk_DESCRIPTOR_RANGE_TYPE_UAV, "Unexpected descriptor range type"); - auto *pTexViewVk = Res.pObject.RawPtr<TextureViewVkImpl>(); - auto *pTexToTransition = ValidatedCast<TextureVkImpl>(pTexViewVk->GetTexture()); - auto State = pTexToTransition->GetState(); - if( (State & Vk_RESOURCE_STATE_UNORDERED_ACCESS) != Vk_RESOURCE_STATE_UNORDERED_ACCESS ) - LOG_ERROR_MESSAGE("Resource \"", pTexToTransition->GetDesc().Name, "\" is not in Vk_RESOURCE_STATE_UNORDERED_ACCESS state. Did you forget to call TransitionShaderResources() or specify COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES flag in a call to CommitShaderResources()?" ); - } - break; - - case CachedResourceType::Sampler: - VERIFY(RangeType == Vk_DESCRIPTOR_RANGE_TYPE_SAMPLER, "Unexpected descriptor range type"); - break; - - default: - // Resource not bound - VERIFY(Res.Type == CachedResourceType::Unknown, "Unexpected resource type"); - VERIFY(Res.pObject == nullptr && Res.CPUDescriptorHandle.ptr == 0, "Bound resource is unexpected"); - } -} -#endif template<class TOperation> __forceinline void PipelineLayout::DescriptorSetLayoutManager::ProcessRootTables(TOperation Operation)const diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index 2126f404..c0627d78 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -497,10 +497,10 @@ bool PipelineStateVkImpl::IsCompatibleWith(const IPipelineState *pPSO)const } -ShaderResourceCacheVk* PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBinding* pShaderResourceBinding, - VulkanUtilities::VulkanCommandBuffer& CmdBuff, - bool CommitResources, - bool TransitionResources)const +ShaderResourceCacheVk* PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBinding* pShaderResourceBinding, + DeviceContextVkImpl* pCtxVkImpl, + bool CommitResources, + bool TransitionResources)const { #ifdef VERIFY_SHADER_BINDINGS if (pShaderResourceBinding == nullptr && !m_pDefaultShaderResBinding) @@ -532,36 +532,32 @@ ShaderResourceCacheVk* PipelineStateVkImpl::CommitAndTransitionShaderResources(I pResBindingVkImpl->dbgVerifyResourceBindings(this); #endif - auto *pDeviceVkImpl = ValidatedCast<RenderDeviceVkImpl>( GetDevice() ); + //auto *pDeviceVkImpl = ValidatedCast<RenderDeviceVkImpl>( GetDevice() ); auto &ResourceCache = pResBindingVkImpl->GetResourceCache(); -#if 0 + if(CommitResources) { - if(m_Desc.IsComputePipeline) - Ctx.AsComputeContext().SetRootSignature( GetVkRootSignature() ); - else - Ctx.AsGraphicsContext().SetRootSignature( GetVkRootSignature() ); - if(TransitionResources) - (m_RootSig.*m_RootSig.TransitionAndCommitDescriptorHandles)(pDeviceVkImpl, ResourceCache, Ctx, m_Desc.IsComputePipeline); + ResourceCache.TransitionResources<false>(pCtxVkImpl); else - (m_RootSig.*m_RootSig.CommitDescriptorHandles)(pDeviceVkImpl, ResourceCache, Ctx, m_Desc.IsComputePipeline); + { +#ifdef VERIFY_SHADER_BINDINGS + ResourceCache.TransitionResources<true>(pCtxVkImpl); +#endif + } + + //if(m_Desc.IsComputePipeline) + // Ctx.AsComputeContext().SetRootSignature( GetVkRootSignature() ); + //else + // Ctx.AsGraphicsContext().SetRootSignature( GetVkRootSignature() ); } else { VERIFY(TransitionResources, "Resources should be transitioned or committed or both"); - m_RootSig.TransitionResources(ResourceCache, Ctx); + ResourceCache.TransitionResources<false>(pCtxVkImpl); } -#endif + return &ResourceCache; } -#if 0 -bool PipelineStateVkImpl::dbgContainsShaderResources()const -{ - return m_RootSig.GetTotalSrvCbvUavSlots(SHADER_VARIABLE_TYPE_STATIC) != 0 || - m_RootSig.GetTotalSrvCbvUavSlots(SHADER_VARIABLE_TYPE_MUTABLE) != 0 || - m_RootSig.GetTotalSrvCbvUavSlots(SHADER_VARIABLE_TYPE_DYNAMIC) != 0; -} -#endif } diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp index 973ab200..29ba4f4f 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp @@ -38,6 +38,8 @@ ShaderResourceBindingVkImpl::ShaderResourceBindingVkImpl( IReferenceCounters *pR m_NumShaders = pPSO->GetNumShaders(); auto *pRenderDeviceVkImpl = ValidatedCast<RenderDeviceVkImpl>(pPSO->GetDevice()); + // This only allocate memory and initialize descriptor sets in the resource cache + // Resources will be initialized by InitializeResourcesInCache() pPSO->GetPipelineLayout().InitResourceCache(pRenderDeviceVkImpl, m_ShaderResourceCache, pPSO->GetResourceCacheDataAllocator()); auto *pResLayoutRawMem = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderResourceLayoutVk", m_NumShaders * sizeof(ShaderResourceLayoutVk)); @@ -51,10 +53,9 @@ ShaderResourceBindingVkImpl::ShaderResourceBindingVkImpl( IReferenceCounters *pR auto &ShaderResLayoutDataAllocator = pPSO->GetShaderResourceLayoutDataAllocator(s); - // http://diligentgraphics.com/diligent-engine/architecture/Vk/shader-resource-layout#Initializing-Resource-Layouts-in-a-Shader-Resource-Binding-Object - SHADER_VARIABLE_TYPE Types[] = {SHADER_VARIABLE_TYPE_STATIC, SHADER_VARIABLE_TYPE_MUTABLE, SHADER_VARIABLE_TYPE_DYNAMIC}; const auto &SrcLayout = pPSO->GetShaderResLayout(ShaderType); - new (m_pResourceLayouts + s) ShaderResourceLayoutVk(*this, SrcLayout, ShaderResLayoutDataAllocator, Types, _countof(Types), m_ShaderResourceCache); + new (m_pResourceLayouts + s) ShaderResourceLayoutVk(*this, SrcLayout, ShaderResLayoutDataAllocator, nullptr, 0, m_ShaderResourceCache); + m_pResourceLayouts[s].InitializeResourcesInCache(); m_ResourceLayoutIndex[ShaderInd] = static_cast<Int8>(s); } diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp index 61cac3db..dbf1db5f 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp @@ -24,10 +24,15 @@ #include "pch.h" #include "ShaderResourceCacheVk.h" +#include "DeviceContextVkImpl.h" +#include "BufferVkImpl.h" +#include "BufferViewVkImpl.h" +#include "TextureViewVkImpl.h" +#include "TextureVkImpl.h" namespace Diligent { - void ShaderResourceCacheVk::Initialize(IMemoryAllocator &MemAllocator, Uint32 NumSets, Uint32 SetSizes[]) + void ShaderResourceCacheVk::InitializeSets(IMemoryAllocator &MemAllocator, Uint32 NumSets, Uint32 SetSizes[]) { // Memory layout: // ______________________________________________________________ @@ -47,18 +52,15 @@ namespace Diligent VERIFY(m_pAllocator == nullptr && m_pMemory == nullptr, "Cache already initialized"); m_pAllocator = &MemAllocator; m_NumSets = NumSets; - Uint32 TotalResources = 0; + m_TotalResources = 0; for(Uint32 t=0; t < NumSets; ++t) - TotalResources += SetSizes[t]; - auto MemorySize = NumSets * sizeof(DescriptorSet) + TotalResources * sizeof(Resource); + m_TotalResources += SetSizes[t]; + auto MemorySize = NumSets * sizeof(DescriptorSet) + m_TotalResources * sizeof(Resource); if(MemorySize > 0) { m_pMemory = ALLOCATE( *m_pAllocator, "Memory for shader resource cache data", MemorySize); auto *pSets = reinterpret_cast<DescriptorSet*>(m_pMemory); auto *pCurrResPtr = reinterpret_cast<Resource*>(pSets + m_NumSets); - for(Uint32 res=0; res < TotalResources; ++res) - new(pCurrResPtr + res) Resource(); - for (Uint32 t = 0; t < NumSets; ++t) { new(&GetDescriptorSet(t)) DescriptorSet(SetSizes[t], SetSizes[t] > 0 ? pCurrResPtr : nullptr); @@ -68,15 +70,19 @@ namespace Diligent } } + void ShaderResourceCacheVk::InitializeResources(Uint32 Set, Uint32 Offset, Uint32 ArraySize, SPIRVShaderResourceAttribs::ResourceType Type) + { + auto &DescrSet = GetDescriptorSet(Set); + for (Uint32 res = 0; res < ArraySize; ++res) + new(&DescrSet.GetResource(Offset + res)) Resource{Type}; + } + ShaderResourceCacheVk::~ShaderResourceCacheVk() { if (m_pMemory) { - Uint32 TotalResources = 0; - for (Uint32 t = 0; t < m_NumSets; ++t) - TotalResources += GetDescriptorSet(t).GetSize(); auto *pResources = reinterpret_cast<Resource*>( reinterpret_cast<DescriptorSet*>(m_pMemory) + m_NumSets); - for(Uint32 res=0; res < TotalResources; ++res) + for(Uint32 res=0; res < m_TotalResources; ++res) pResources[res].~Resource(); for (Uint32 t = 0; t < m_NumSets; ++t) GetDescriptorSet(t).~DescriptorSet(); @@ -84,4 +90,89 @@ namespace Diligent m_pAllocator->Free(m_pMemory); } } + + template<bool VerifyOnly> + void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl *pCtxVkImpl) + { + auto *pResources = reinterpret_cast<Resource*>(reinterpret_cast<DescriptorSet*>(m_pMemory) + m_NumSets); + for (Uint32 res = 0; res < m_TotalResources; ++res) + { + auto &Res = pResources[res]; + switch (Res.Type) + { + case SPIRVShaderResourceAttribs::ResourceType::UniformBuffer: + case SPIRVShaderResourceAttribs::ResourceType::StorageBuffer: + { + auto *pBufferVk = Res.pObject.RawPtr<BufferVkImpl>(); + VkAccessFlags RequiredAccessFlags = + Res.Type == SPIRVShaderResourceAttribs::ResourceType::UniformBuffer ? + VK_ACCESS_UNIFORM_READ_BIT : + (VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT); + if(pBufferVk->GetAccessFlags() != RequiredAccessFlags) + { + if(VerifyOnly) + LOG_ERROR_MESSAGE("Buffer \"", pBufferVk->GetDesc().Name, "\" is not in correct state. Did you forget to call TransitionShaderResources() or specify COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES flag in a call to CommitShaderResources()?"); + else + pCtxVkImpl->BufferMemoryBarrier(*pBufferVk, RequiredAccessFlags); + } + } + break; + + case SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer: + case SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer: + { + auto *pBuffViewVk = Res.pObject.RawPtr<BufferViewVkImpl>(); + auto *pBufferVk = ValidatedCast<BufferVkImpl>(pBuffViewVk->GetBuffer()); + VkAccessFlags RequiredAccessFlags = + Res.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer ? + VK_ACCESS_SHADER_READ_BIT : + (VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT); + if (pBufferVk->GetAccessFlags() != RequiredAccessFlags) + { + if (VerifyOnly) + LOG_ERROR_MESSAGE("Buffer \"", pBufferVk->GetDesc().Name, "\" is not in correct state. Did you forget to call TransitionShaderResources() or specify COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES flag in a call to CommitShaderResources()?"); + else + pCtxVkImpl->BufferMemoryBarrier(*pBufferVk, RequiredAccessFlags); + } + } + break; + + case SPIRVShaderResourceAttribs::ResourceType::SeparateImage: + case SPIRVShaderResourceAttribs::ResourceType::SampledImage: + case SPIRVShaderResourceAttribs::ResourceType::StorageImage: + { + auto *pTextureViewVk = Res.pObject.RawPtr<TextureViewVkImpl>(); + auto *pTextureVk = ValidatedCast<TextureVkImpl>(pTextureViewVk->GetTexture()); + VkImageLayout RequiredLayout = + Res.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage ? + VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + if(pTextureVk->GetLayout() != RequiredLayout) + { + if (VerifyOnly) + LOG_ERROR_MESSAGE("Texture \"", pTextureVk->GetDesc().Name, "\" is not in correct state. Did you forget to call TransitionShaderResources() or specify COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES flag in a call to CommitShaderResources()?"); + else + pCtxVkImpl->TransitionImageLayout(*pTextureVk, RequiredLayout); + } + } + break; + + case SPIRVShaderResourceAttribs::ResourceType::AtomicCounter: + { + // Nothing to do with atomic counters + } + break; + + case SPIRVShaderResourceAttribs::ResourceType::SeparateSampler: + { + // Nothing to do with samplers + } + break; + + default: UNEXPECTED("Unexpected resource type"); + } + } + } + + template void ShaderResourceCacheVk::TransitionResources<false>(DeviceContextVkImpl *pCtxVkImpl); + template void ShaderResourceCacheVk::TransitionResources<true>(DeviceContextVkImpl *pCtxVkImpl); } diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp index 6010c4d9..98651f09 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp @@ -270,7 +270,8 @@ void ShaderResourceLayoutVk::Initialize(const VulkanUtilities::VulkanLogicalDevi { // Initialize resource cache to store static resources VERIFY_EXPR(pPipelineLayout == nullptr && pSPIRV == nullptr); - m_pResourceCache->Initialize(GetRawAllocator(), static_cast<Uint32>(StaticResCacheSetSizes.size()), StaticResCacheSetSizes.data()); + m_pResourceCache->InitializeSets(GetRawAllocator(), static_cast<Uint32>(StaticResCacheSetSizes.size()), StaticResCacheSetSizes.data()); + InitializeResourcesInCache(); #ifdef _DEBUG for(SPIRVShaderResourceAttribs::ResourceType ResType = SPIRVShaderResourceAttribs::ResourceType::UniformBuffer; ResType < SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes; @@ -479,6 +480,9 @@ void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject* } } DescrImgInfo.imageView = pTexViewVk->GetVulkanImageView(); + // If descriptorType is VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, for each descriptor that will be accessed + // via load or store operations the imageLayout member for corresponding elements of pImageInfo + // must be VK_IMAGE_LAYOUT_GENERAL (13.2.4) DescrImgInfo.imageLayout = IsStorageImage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; UpdateDescriptorHandle(vkDescrSet, ArrayInd, &DescrImgInfo, nullptr, nullptr); } @@ -529,6 +533,7 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject *pObj, Uint3 } #endif auto &DstRes = DstDescrSet.GetResource(CacheOffset + ArrayIndex); + VERIFY(DstRes.Type == SpirvAttribs.Type, "Inconsistent types"); if( pObj ) { @@ -571,7 +576,7 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject *pObj, Uint3 LOG_ERROR_MESSAGE( "Shader variable \"", SpirvAttribs.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." ); } - DstRes = ShaderResourceCacheVk::Resource(); + DstRes.pObject.Release(); } } @@ -740,6 +745,7 @@ void ShaderResourceLayoutVk::dbgVerifyBindings()const { auto &CachedDescrSet = m_pResourceCache->GetDescriptorSet(Res.DescriptorSet); const auto &CachedRes = CachedDescrSet.GetResource(Res.CacheOffset + ArrInd); + VERIFY(CachedRes.Type == Res.SpirvAttribs.Type, "Inconsistent types"); if(CachedRes.pObject == nullptr && !(Res.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && Res.SpirvAttribs.StaticSamplerInd >= 0)) { @@ -796,4 +802,14 @@ const Char* ShaderResourceLayoutVk::GetShaderName()const return ""; } +void ShaderResourceLayoutVk::InitializeResourcesInCache() +{ + VERIFY_EXPR(m_pResourceCache); + for(Uint32 r = 0; r < GetTotalResourceCount(); ++r) + { + const auto& Res = GetResource(r); + m_pResourceCache->InitializeResources(Res.DescriptorSet, Res.CacheOffset, Res.SpirvAttribs.ArraySize, Res.SpirvAttribs.Type); + } +} + } diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp index a4c996a6..f63bd7d6 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp @@ -175,7 +175,8 @@ void VulkanCommandBuffer::TransitionImageLayout(VkCommandBuffer CmdBuffer, // supports all types of device access case VK_IMAGE_LAYOUT_GENERAL: - UNEXPECTED("General layout is not recommended"); + // VK_IMAGE_LAYOUT_GENERAL must be used for image load/store operations (13.2.4) + ImgBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; break; // must only be used as a color or resolve attachment in a VkFramebuffer (11.4) @@ -243,7 +244,8 @@ void VulkanCommandBuffer::TransitionImageLayout(VkCommandBuffer CmdBuffer, break; case VK_IMAGE_LAYOUT_GENERAL: - UNEXPECTED("General layout is not recommended due to inefficiency"); + // VK_IMAGE_LAYOUT_GENERAL must be used for image load/store operations (13.2.4) + ImgBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; break; case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: @@ -355,6 +357,54 @@ void VulkanCommandBuffer::TransitionImageLayout(VkCommandBuffer CmdBuffer, // of the pipeline stages in dstStageMask (6.6) } + +void VulkanCommandBuffer::BufferMemoryBarrier(VkCommandBuffer CmdBuffer, + VkBuffer Buffer, + VkAccessFlags srcAccessMask, + VkAccessFlags dstAccessMask, + VkPipelineStageFlags SrcStages, + VkPipelineStageFlags DestStages) +{ + VkBufferMemoryBarrier BuffBarrier = {}; + BuffBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + BuffBarrier.pNext = nullptr; + BuffBarrier.srcAccessMask = srcAccessMask; + BuffBarrier.dstAccessMask = dstAccessMask; + BuffBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + BuffBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + BuffBarrier.buffer = Buffer; + BuffBarrier.offset = 0; + BuffBarrier.size = VK_WHOLE_SIZE; + if (SrcStages == 0) + { + if(BuffBarrier.srcAccessMask != 0) + SrcStages = PipelineStageFromAccessFlags(BuffBarrier.srcAccessMask); + else + { + // An execution dependency with only VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT in the source stage + // mask will effectively not wait for any prior commands to complete. (6.1.2) + SrcStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + } + } + + if (DestStages == 0) + { + VERIFY(BuffBarrier.dstAccessMask != 0, "Dst access mask must not be zero"); + DestStages = PipelineStageFromAccessFlags(BuffBarrier.dstAccessMask); + } + + vkCmdPipelineBarrier(CmdBuffer, + SrcStages, // must not be 0 + DestStages, // must not be 0 + 0, // a bitmask specifying how execution and memory dependencies are formed + 0, // memoryBarrierCount + nullptr, // pMemoryBarriers + 1, // bufferMemoryBarrierCount + &BuffBarrier, // pBufferMemoryBarriers + 0, + nullptr); +} + void VulkanCommandBuffer::FlushBarriers() { |
