summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineVulkan
diff options
context:
space:
mode:
authorassiduous <assiduous@diligentgraphics.com>2020-08-15 22:42:13 +0000
committerassiduous <assiduous@diligentgraphics.com>2020-08-15 22:42:13 +0000
commitdf3a2c7c744eae194c79187a59914c6662f69b52 (patch)
tree6f67919092b671b4a0fb637db26f75293f849886 /Graphics/GraphicsEngineVulkan
parentFixed Visual Studio 16.7 build error (diff)
parentVk backend: not setting render pass in SetPipelineState (diff)
downloadDiligentCore-df3a2c7c744eae194c79187a59914c6662f69b52.tar.gz
DiligentCore-df3a2c7c744eae194c79187a59914c6662f69b52.zip
Added render passes to the API (fixed https://github.com/DiligentGraphics/DiligentCore/issues/9)
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
-rw-r--r--Graphics/GraphicsEngineVulkan/CMakeLists.txt6
-rw-r--r--Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp21
-rw-r--r--Graphics/GraphicsEngineVulkan/include/FramebufferVkImpl.hpp63
-rw-r--r--Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp19
-rw-r--r--Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp17
-rw-r--r--Graphics/GraphicsEngineVulkan/include/RenderPassCache.hpp15
-rw-r--r--Graphics/GraphicsEngineVulkan/include/RenderPassVkImpl.hpp63
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp1
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp5
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp11
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp28
-rw-r--r--Graphics/GraphicsEngineVulkan/interface/FramebufferVk.h64
-rw-r--r--Graphics/GraphicsEngineVulkan/interface/PipelineStateVk.h9
-rw-r--r--Graphics/GraphicsEngineVulkan/interface/RenderPassVk.h64
-rw-r--r--Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp216
-rw-r--r--Graphics/GraphicsEngineVulkan/src/FramebufferVkImpl.cpp84
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp3
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp167
-rw-r--r--Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp52
-rw-r--r--Graphics/GraphicsEngineVulkan/src/RenderPassCache.cpp42
-rw-r--r--Graphics/GraphicsEngineVulkan/src/RenderPassVkImpl.cpp166
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp25
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp42
-rw-r--r--Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp4
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp106
25 files changed, 1102 insertions, 191 deletions
diff --git a/Graphics/GraphicsEngineVulkan/CMakeLists.txt b/Graphics/GraphicsEngineVulkan/CMakeLists.txt
index 28cf8b0f..93a811b1 100644
--- a/Graphics/GraphicsEngineVulkan/CMakeLists.txt
+++ b/Graphics/GraphicsEngineVulkan/CMakeLists.txt
@@ -11,6 +11,7 @@ set(INCLUDE
include/DescriptorPoolManager.hpp
include/DeviceContextVkImpl.hpp
include/FenceVkImpl.hpp
+ include/FramebufferVkImpl.hpp
include/VulkanDynamicHeap.hpp
include/FramebufferCache.hpp
include/GenerateMipsVkHelper.hpp
@@ -20,6 +21,7 @@ set(INCLUDE
include/QueryManagerVk.hpp
include/QueryVkImpl.hpp
include/RenderDeviceVkImpl.hpp
+ include/RenderPassVkImpl.hpp
include/RenderPassCache.hpp
include/SamplerVkImpl.hpp
include/ShaderVkImpl.hpp
@@ -57,9 +59,11 @@ set(INTERFACE
interface/DeviceContextVk.h
interface/EngineFactoryVk.h
interface/FenceVk.h
+ interface/FramebufferVk.h
interface/PipelineStateVk.h
interface/QueryVk.h
interface/RenderDeviceVk.h
+ interface/RenderPassVk.h
interface/SamplerVk.h
interface/ShaderVk.h
interface/ShaderResourceBindingVk.h
@@ -78,6 +82,7 @@ set(SRC
src/DeviceContextVkImpl.cpp
src/EngineFactoryVk.cpp
src/FenceVkImpl.cpp
+ src/FramebufferVkImpl.cpp
src/VulkanDynamicHeap.cpp
src/FramebufferCache.cpp
src/GenerateMipsVkHelper.cpp
@@ -86,6 +91,7 @@ set(SRC
src/QueryManagerVk.cpp
src/QueryVkImpl.cpp
src/RenderDeviceVkImpl.cpp
+ src/RenderPassVkImpl.cpp
src/RenderPassCache.cpp
src/SamplerVkImpl.cpp
src/ShaderVkImpl.cpp
diff --git a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp
index 83e2c077..ebca0282 100644
--- a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp
@@ -45,6 +45,8 @@
#include "TextureVkImpl.hpp"
#include "PipelineStateVkImpl.hpp"
#include "QueryVkImpl.hpp"
+#include "FramebufferVkImpl.hpp"
+#include "RenderPassVkImpl.hpp"
#include "HashUtils.hpp"
#include "ManagedVulkanObject.hpp"
#include "QueryManagerVk.hpp"
@@ -53,8 +55,6 @@
namespace Diligent
{
-class RenderDeviceVkImpl;
-
struct DeviceContextVkImplTraits
{
using BufferType = BufferVkImpl;
@@ -63,6 +63,8 @@ struct DeviceContextVkImplTraits
using DeviceType = RenderDeviceVkImpl;
using ICommandQueueType = ICommandQueueVk;
using QueryType = QueryVkImpl;
+ using FramebufferType = FramebufferVkImpl;
+ using RenderPassType = RenderPassVkImpl;
};
/// Device context implementation in Vulkan backend.
@@ -133,6 +135,15 @@ public:
ITextureView* pDepthStencil,
RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final;
+ /// Implementation of IDeviceContext::BeginRenderPass() in Direct3D11 backend.
+ virtual void DILIGENT_CALL_TYPE BeginRenderPass(const BeginRenderPassAttribs& Attribs) override final;
+
+ /// Implementation of IDeviceContext::NextSubpass() in Direct3D11 backend.
+ virtual void DILIGENT_CALL_TYPE NextSubpass() override final;
+
+ /// Implementation of IDeviceContext::EndRenderPass() in Direct3D11 backend.
+ virtual void DILIGENT_CALL_TYPE EndRenderPass() override final;
+
// clang-format off
/// Implementation of IDeviceContext::Draw() in Vulkan backend.
virtual void DILIGENT_CALL_TYPE Draw (const DrawAttribs& Attribs) override final;
@@ -427,11 +438,11 @@ private:
/// Render pass that matches currently bound render targets.
/// This render pass may or may not be currently set in the command buffer
- VkRenderPass m_RenderPass = VK_NULL_HANDLE;
+ VkRenderPass m_vkRenderPass = VK_NULL_HANDLE;
/// Framebuffer that matches currently bound render targets.
/// This framebuffer may or may not be currently set in the command buffer
- VkFramebuffer m_Framebuffer = VK_NULL_HANDLE;
+ VkFramebuffer m_vkFramebuffer = VK_NULL_HANDLE;
FixedBlockMemoryAllocator m_CmdListAllocator;
@@ -489,6 +500,8 @@ private:
std::unique_ptr<QueryManagerVk> m_QueryMgr;
Int32 m_ActiveQueriesCounter = 0;
+
+ std::vector<VkClearValue> m_vkClearValues;
};
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/include/FramebufferVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/FramebufferVkImpl.hpp
new file mode 100644
index 00000000..3e15852c
--- /dev/null
+++ b/Graphics/GraphicsEngineVulkan/include/FramebufferVkImpl.hpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2019-2020 Diligent Graphics LLC
+ * Copyright 2015-2019 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Declaration of Diligent::FramebufferVkImpl class
+
+#include "FramebufferVk.h"
+#include "FramebufferBase.hpp"
+#include "RenderDeviceVkImpl.hpp"
+#include "VulkanUtilities/VulkanObjectWrappers.hpp"
+
+namespace Diligent
+{
+
+class FixedBlockMemoryAllocator;
+
+/// Render pass implementation in Direct3D11 backend.
+class FramebufferVkImpl final : public FramebufferBase<IFramebufferVk, RenderDeviceVkImpl>
+{
+public:
+ using TFramebufferBase = FramebufferBase<IFramebufferVk, RenderDeviceVkImpl>;
+
+ FramebufferVkImpl(IReferenceCounters* pRefCounters,
+ RenderDeviceVkImpl* pDevice,
+ const FramebufferDesc& Desc);
+ ~FramebufferVkImpl();
+
+ VkFramebuffer GetVkFramebuffer() const override final
+ {
+ return m_VkFramebuffer;
+ }
+
+private:
+ VulkanUtilities::FramebufferWrapper m_VkFramebuffer;
+};
+
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp
index aca69cac..b8d5b0ec 100644
--- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp
@@ -68,8 +68,8 @@ public:
/// Implementation of IPipelineState::IsCompatibleWith() in Vulkan backend.
virtual bool DILIGENT_CALL_TYPE IsCompatibleWith(const IPipelineState* pPSO) const override final;
- /// Implementation of IPipelineStateVk::GetVkRenderPass().
- virtual VkRenderPass DILIGENT_CALL_TYPE GetVkRenderPass() const override final { return m_RenderPass; }
+ /// Implementation of IPipelineStateVk::GetRenderPass().
+ virtual IRenderPassVk* DILIGENT_CALL_TYPE GetRenderPass() const override final { return m_pRenderPass.RawPtr<IRenderPassVk>(); }
/// Implementation of IPipelineStateVk::GetVkPipeline().
virtual VkPipeline DILIGENT_CALL_TYPE GetVkPipeline() const override final { return m_Pipeline; }
@@ -113,13 +113,13 @@ public:
return m_SRBMemAllocator;
}
- static VkRenderPassCreateInfo GetRenderPassCreateInfo(Uint32 NumRenderTargets,
- const TEXTURE_FORMAT RTVFormats[],
- TEXTURE_FORMAT DSVFormat,
- Uint32 SampleCount,
- std::array<VkAttachmentDescription, MAX_RENDER_TARGETS + 1>& Attachments,
- std::array<VkAttachmentReference, MAX_RENDER_TARGETS + 1>& AttachmentReferences,
- VkSubpassDescription& SubpassDesc);
+ static RenderPassDesc 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);
void InitializeStaticSRBResources(ShaderResourceCacheVk& ResourceCache) const;
@@ -152,7 +152,6 @@ private:
std::array<VulkanUtilities::ShaderModuleWrapper, MAX_SHADERS_IN_PIPELINE> m_ShaderModules;
- VkRenderPass m_RenderPass = VK_NULL_HANDLE; // Render passes are managed by the render device
VulkanUtilities::PipelineWrapper m_Pipeline;
PipelineLayout m_PipelineLayout;
diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp
index 7204cad7..38bd4893 100644
--- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp
@@ -98,6 +98,19 @@ public:
/// Implementation of IRenderDevice::CreateQuery() in Vulkan backend.
virtual void DILIGENT_CALL_TYPE CreateQuery(const QueryDesc& Desc, IQuery** ppQuery) override final;
+ /// Implementation of IRenderDevice::CreateRenderPass() in Vulkan backend.
+ virtual void DILIGENT_CALL_TYPE CreateRenderPass(const RenderPassDesc& Desc,
+ IRenderPass** ppRenderPass) override final;
+
+ void CreateRenderPass(const RenderPassDesc& Desc,
+ IRenderPass** ppRenderPass,
+ bool IsDeviceInternal);
+
+
+ /// Implementation of IRenderDevice::CreateFramebuffer() in Vulkan backend.
+ virtual void DILIGENT_CALL_TYPE CreateFramebuffer(const FramebufferDesc& Desc,
+ IFramebuffer** ppFramebuffer) override final;
+
/// Implementation of IRenderDeviceVk::GetVkDevice().
virtual VkDevice DILIGENT_CALL_TYPE GetVkDevice() override final { return m_LogicalVkDevice->GetVkDevice(); }
@@ -144,7 +157,7 @@ public:
const VulkanUtilities::VulkanLogicalDevice& GetLogicalDevice() { return *m_LogicalVkDevice; }
FramebufferCache& GetFramebufferCache() { return m_FramebufferCache; }
- RenderPassCache& GetRenderPassCache() { return m_RenderPassCache; }
+ RenderPassCache& GetImplicitRenderPassCache() { return m_ImplicitRenderPassCache; }
VulkanUtilities::VulkanMemoryAllocation AllocateMemory(const VkMemoryRequirements& MemReqs, VkMemoryPropertyFlags MemoryProperties)
{
@@ -173,7 +186,7 @@ private:
EngineVkCreateInfo m_EngineAttribs;
FramebufferCache m_FramebufferCache;
- RenderPassCache m_RenderPassCache;
+ RenderPassCache m_ImplicitRenderPassCache;
DescriptorSetAllocator m_DescriptorSetAllocator;
DescriptorPoolManager m_DynamicDescriptorPool;
diff --git a/Graphics/GraphicsEngineVulkan/include/RenderPassCache.hpp b/Graphics/GraphicsEngineVulkan/include/RenderPassCache.hpp
index bfab6c53..ba21fcd9 100644
--- a/Graphics/GraphicsEngineVulkan/include/RenderPassCache.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/RenderPassCache.hpp
@@ -36,17 +36,18 @@
#include "Constants.h"
#include "HashUtils.hpp"
#include "VulkanUtilities/VulkanObjectWrappers.hpp"
+#include "RefCntAutoPtr.hpp"
namespace Diligent
{
class RenderDeviceVkImpl;
+class RenderPassVkImpl;
+
class RenderPassCache
{
public:
- RenderPassCache(RenderDeviceVkImpl& DeviceVk) noexcept :
- m_DeviceVkImpl{DeviceVk}
- {}
+ RenderPassCache(RenderDeviceVkImpl& DeviceVk) noexcept;
// clang-format off
RenderPassCache (const RenderPassCache&) = delete;
@@ -123,7 +124,9 @@ public:
mutable size_t Hash = 0;
};
- VkRenderPass GetRenderPass(const RenderPassCacheKey& Key);
+ RenderPassVkImpl* GetRenderPass(const RenderPassCacheKey& Key);
+
+ void Destroy();
private:
struct RenderPassCacheKeyHash
@@ -136,8 +139,8 @@ private:
RenderDeviceVkImpl& m_DeviceVkImpl;
- std::mutex m_Mutex;
- std::unordered_map<RenderPassCacheKey, VulkanUtilities::RenderPassWrapper, RenderPassCacheKeyHash> m_Cache;
+ std::mutex m_Mutex;
+ std::unordered_map<RenderPassCacheKey, RefCntAutoPtr<RenderPassVkImpl>, RenderPassCacheKeyHash> m_Cache;
};
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/include/RenderPassVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderPassVkImpl.hpp
new file mode 100644
index 00000000..5c77784f
--- /dev/null
+++ b/Graphics/GraphicsEngineVulkan/include/RenderPassVkImpl.hpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2019-2020 Diligent Graphics LLC
+ * Copyright 2015-2019 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Declaration of Diligent::RenderPassVkImpl class
+
+#include "RenderDeviceVk.h"
+#include "RenderPassVk.h"
+#include "RenderPassBase.hpp"
+#include "RenderDeviceVkImpl.hpp"
+#include "VulkanUtilities/VulkanObjectWrappers.hpp"
+
+namespace Diligent
+{
+
+class FixedBlockMemoryAllocator;
+
+/// Render pass implementation in Direct3D11 backend.
+class RenderPassVkImpl final : public RenderPassBase<IRenderPassVk, RenderDeviceVkImpl>
+{
+public:
+ using TRenderPassBase = RenderPassBase<IRenderPassVk, RenderDeviceVkImpl>;
+
+ RenderPassVkImpl(IReferenceCounters* pRefCounters,
+ RenderDeviceVkImpl* pDevice,
+ const RenderPassDesc& Desc,
+ bool IsDeviceInternal);
+ ~RenderPassVkImpl();
+
+ /// Implementation of ISamplerVk::GetVkRenderPass().
+ virtual VkRenderPass DILIGENT_CALL_TYPE GetVkRenderPass() const override final { return m_VkRenderPass; }
+
+private:
+ VulkanUtilities::RenderPassWrapper m_VkRenderPass;
+};
+
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp
index 172c82a8..a5278cb7 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp
@@ -117,6 +117,7 @@ public:
VkDescriptorImageInfo GetImageDescriptorWriteInfo (bool IsImmutableSampler)const;
VkBufferView GetBufferViewWriteInfo () const;
VkDescriptorImageInfo GetSamplerDescriptorWriteInfo() const;
+ VkDescriptorImageInfo GetInputAttachmentDescriptorWriteInfo() const;
// clang-format on
};
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp
index 07050821..a6d20641 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp
@@ -260,6 +260,11 @@ public:
VkDescriptorSet vkDescrSet,
Uint32 ArrayInd) const;
+ void CacheInputAttachment(IDeviceObject* pTexView,
+ ShaderResourceCacheVk::Resource& DstRes,
+ VkDescriptorSet vkDescrSet,
+ Uint32 ArrayInd) const;
+
template <typename ObjectType, typename TPreUpdateObject>
bool UpdateCachedResource(ShaderResourceCacheVk::Resource& DstRes,
RefCntAutoPtr<ObjectType>&& pObject,
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp
index 15420ead..dbba5b7e 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp
@@ -65,7 +65,7 @@ VkSamplerAddressMode AddressModeToVkAddressMode(TEXTURE_ADDRESS_MODE AddressMode
VkBorderColor BorderColorToVkBorderColor(const Float32 BorderColor[]);
VkAccessFlags ResourceStateFlagsToVkAccessFlags(RESOURCE_STATE StateFlags);
-VkImageLayout ResourceStateToVkImageLayout(RESOURCE_STATE StateFlag);
+VkImageLayout ResourceStateToVkImageLayout(RESOURCE_STATE StateFlag, bool IsInsideRenderPass = false);
RESOURCE_STATE VkAccessFlagsToResourceStates(VkAccessFlags AccessFlags);
RESOURCE_STATE VkImageLayoutToResourceState(VkImageLayout Layout);
@@ -73,4 +73,13 @@ RESOURCE_STATE VkImageLayoutToResourceState(VkImageLayout Layout);
SURFACE_TRANSFORM VkSurfaceTransformFlagToSurfaceTransform(VkSurfaceTransformFlagBitsKHR vkTransformFlag);
VkSurfaceTransformFlagBitsKHR SurfaceTransformToVkSurfaceTransformFlag(SURFACE_TRANSFORM SrfTransform);
+VkAttachmentLoadOp AttachmentLoadOpToVkAttachmentLoadOp(ATTACHMENT_LOAD_OP LoadOp);
+ATTACHMENT_LOAD_OP VkAttachmentLoadOpToAttachmentLoadOp(VkAttachmentLoadOp VkLoadOp);
+
+VkAttachmentStoreOp AttachmentStoreOpToVkAttachmentStoreOp(ATTACHMENT_STORE_OP StoreOp);
+ATTACHMENT_STORE_OP VkAttachmentStoreOpToAttachmentStoreOp(VkAttachmentStoreOp VkStoreOp);
+
+VkPipelineStageFlags PipelineStageFlagsToVkPipelineStageFlags(PIPELINE_STAGE_FLAGS PipelineStageFlags);
+VkAccessFlags AccessFlagsToVkAccessFlags(ACCESS_FLAGS AccessFlags);
+
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp
index 1465024b..5b4fc1e7 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp
@@ -156,7 +156,12 @@ public:
vkCmdDispatchIndirect(m_VkCmdBuffer, Buffer, Offset);
}
- __forceinline void BeginRenderPass(VkRenderPass RenderPass, VkFramebuffer Framebuffer, uint32_t FramebufferWidth, uint32_t FramebufferHeight)
+ __forceinline void BeginRenderPass(VkRenderPass RenderPass,
+ VkFramebuffer Framebuffer,
+ uint32_t FramebufferWidth,
+ uint32_t FramebufferHeight,
+ uint32_t ClearValueCount = 0,
+ const VkClearValue* pClearValues = nullptr)
{
VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
VERIFY(m_State.RenderPass == VK_NULL_HANDLE, "Current pass has not been ended");
@@ -170,13 +175,13 @@ public:
BeginInfo.framebuffer = Framebuffer;
// The render area MUST be contained within the framebuffer dimensions (7.4)
BeginInfo.renderArea = {{0, 0}, {FramebufferWidth, FramebufferHeight}};
- BeginInfo.clearValueCount = 0;
- BeginInfo.pClearValues = nullptr; // an array of VkClearValue structures that contains clear values for
- // each attachment, if the attachment uses a loadOp value of VK_ATTACHMENT_LOAD_OP_CLEAR
- // or if the attachment has a depth/stencil format and uses a stencilLoadOp value of
- // VK_ATTACHMENT_LOAD_OP_CLEAR. The array is indexed by attachment number. Only elements
- // corresponding to cleared attachments are used. Other elements of pClearValues are
- // ignored (7.4)
+ BeginInfo.clearValueCount = ClearValueCount;
+ BeginInfo.pClearValues = pClearValues; // an array of VkClearValue structures that contains clear values for
+ // each attachment, if the attachment uses a loadOp value of VK_ATTACHMENT_LOAD_OP_CLEAR
+ // or if the attachment has a depth/stencil format and uses a stencilLoadOp value of
+ // VK_ATTACHMENT_LOAD_OP_CLEAR. The array is indexed by attachment number. Only elements
+ // corresponding to cleared attachments are used. Other elements of pClearValues are
+ // ignored (7.4)
vkCmdBeginRenderPass(m_VkCmdBuffer, &BeginInfo,
VK_SUBPASS_CONTENTS_INLINE // the contents of the subpass will be recorded inline in the
@@ -208,6 +213,13 @@ public:
}
}
+ __forceinline void NextSubpass()
+ {
+ VERIFY(m_State.RenderPass != VK_NULL_HANDLE, "Render pass has not been started");
+ VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
+ vkCmdNextSubpass(m_VkCmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
+ }
+
__forceinline void EndCommandBuffer()
{
VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
diff --git a/Graphics/GraphicsEngineVulkan/interface/FramebufferVk.h b/Graphics/GraphicsEngineVulkan/interface/FramebufferVk.h
new file mode 100644
index 00000000..9edfb2eb
--- /dev/null
+++ b/Graphics/GraphicsEngineVulkan/interface/FramebufferVk.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2019-2020 Diligent Graphics LLC
+ * Copyright 2015-2019 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::IFramebufferVk interface
+
+#include "../../GraphicsEngine/interface/Framebuffer.h"
+
+DILIGENT_BEGIN_NAMESPACE(Diligent)
+
+// {846BE360-D89B-41AD-B089-7F2439ADCE3A}
+static const INTERFACE_ID IID_FramebufferVk =
+ {0x846be360, 0xd89b, 0x41ad, {0xb0, 0x89, 0x7f, 0x24, 0x39, 0xad, 0xce, 0x3a}};
+
+#define DILIGENT_INTERFACE_NAME IFramebufferVk
+#include "../../../Primitives/interface/DefineInterfaceHelperMacros.h"
+
+#define IFramebufferVkInclusiveMethods \
+ /*IFramebufferInclusiveMethods*/ IDeviceObjectInclusiveMethods; \
+ IFramebufferVkMethods FramebufferVk
+
+/// Exposes Vulkan-specific functionality of a Framebuffer object.
+DILIGENT_BEGIN_INTERFACE(IFramebufferVk, IFramebuffer)
+{
+ /// Returns a Vulkan framebuffer object handle
+ VIRTUAL VkFramebuffer METHOD(GetVkFramebuffer)() CONST PURE;
+};
+DILIGENT_END_INTERFACE
+
+#include "../../../Primitives/interface/UndefInterfaceHelperMacros.h"
+
+#if DILIGENT_C_INTERFACE
+
+# define IFramebufferVk_GetVkFramebuffer(This) CALL_IFACE_METHOD(FramebufferVk, GetVkFramebuffer, This)
+
+#endif
+
+DILIGENT_END_NAMESPACE // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/interface/PipelineStateVk.h b/Graphics/GraphicsEngineVulkan/interface/PipelineStateVk.h
index 679b6e73..f3377f08 100644
--- a/Graphics/GraphicsEngineVulkan/interface/PipelineStateVk.h
+++ b/Graphics/GraphicsEngineVulkan/interface/PipelineStateVk.h
@@ -31,6 +31,7 @@
/// Definition of the Diligent::IPipeplineStateVk interface
#include "../../GraphicsEngine/interface/PipelineState.h"
+#include "RenderPassVk.h"
DILIGENT_BEGIN_NAMESPACE(Diligent)
@@ -48,8 +49,8 @@ static const INTERFACE_ID IID_PipelineStateVk =
/// Exposes Vulkan-specific functionality of a pipeline state object.
DILIGENT_BEGIN_INTERFACE(IPipelineStateVk, IPipelineState)
{
- /// Returns handle to a vulkan render pass object.
- VIRTUAL VkRenderPass METHOD(GetVkRenderPass)(THIS) CONST PURE;
+ /// Returns the pointer to the internal render pass object.
+ VIRTUAL IRenderPassVk* METHOD(GetRenderPass)(THIS) CONST PURE;
/// Returns handle to a vulkan pipeline pass object.
VIRTUAL VkPipeline METHOD(GetVkPipeline)(THIS) CONST PURE;
@@ -62,8 +63,8 @@ DILIGENT_END_INTERFACE
// clang-format off
-# define IPipelineStateVk_GetVkRenderPass(This) CALL_IFACE_METHOD(PipelineStateVk, GetVkRenderPass, This)
-# define IPipelineStateVk_GetVkPipeline(This) CALL_IFACE_METHOD(PipelineStateVk, GetVkPipeline, This)
+# define IPipelineStateVk_GetRenderPass(This) CALL_IFACE_METHOD(PipelineStateVk, GetRenderPass, This)
+# define IPipelineStateVk_GetVkPipeline(This) CALL_IFACE_METHOD(PipelineStateVk, GetVkPipeline, This)
// clang-format on
diff --git a/Graphics/GraphicsEngineVulkan/interface/RenderPassVk.h b/Graphics/GraphicsEngineVulkan/interface/RenderPassVk.h
new file mode 100644
index 00000000..6096e723
--- /dev/null
+++ b/Graphics/GraphicsEngineVulkan/interface/RenderPassVk.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2019-2020 Diligent Graphics LLC
+ * Copyright 2015-2019 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::IRenderPassVk interface
+
+#include "../../GraphicsEngine/interface/RenderPass.h"
+
+DILIGENT_BEGIN_NAMESPACE(Diligent)
+
+// {3DE6938F-D34D-4135-A6FA-15A89E9525D0}
+static const INTERFACE_ID IID_RenderPassVk =
+ {0x3de6938f, 0xd34d, 0x4135, {0xa6, 0xfa, 0x15, 0xa8, 0x9e, 0x95, 0x25, 0xd0}};
+
+#define DILIGENT_INTERFACE_NAME IRenderPassVk
+#include "../../../Primitives/interface/DefineInterfaceHelperMacros.h"
+
+#define IRenderPassVkInclusiveMethods \
+ /*IRenderPassInclusiveMethods*/ IDeviceObjectInclusiveMethods; \
+ IRenderPassVkMethods RenderPassVk
+
+/// Exposes Vulkan-specific functionality of a RenderPass object.
+DILIGENT_BEGIN_INTERFACE(IRenderPassVk, IRenderPass)
+{
+ /// Returns a Vulkan RenderPass object handle
+ VIRTUAL VkRenderPass METHOD(GetVkRenderPass)() CONST PURE;
+};
+DILIGENT_END_INTERFACE
+
+#include "../../../Primitives/interface/UndefInterfaceHelperMacros.h"
+
+#if DILIGENT_C_INTERFACE
+
+# define IRenderPassVk_GetVkRenderPass(This) CALL_IFACE_METHOD(RenderPassVk, GetVkRenderPass, This)
+
+#endif
+
+DILIGENT_END_NAMESPACE // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
index d61ddc97..619ec23c 100644
--- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
@@ -32,6 +32,7 @@
#include "PipelineStateVkImpl.hpp"
#include "TextureVkImpl.hpp"
#include "BufferVkImpl.hpp"
+#include "RenderPassVkImpl.hpp"
#include "VulkanTypeConversions.hpp"
#include "CommandListVkImpl.hpp"
#include "FenceVkImpl.hpp"
@@ -114,6 +115,8 @@ DeviceContextVkImpl::DeviceContextVkImpl(IReferenceCounters* p
RefCntAutoPtr<IBuffer> pDummyVB;
m_pDevice->CreateBuffer(DummyVBDesc, nullptr, &pDummyVB);
m_DummyVB = pDummyVB.RawPtr<BufferVkImpl>();
+
+ m_vkClearValues.reserve(16);
}
DeviceContextVkImpl::~DeviceContextVkImpl()
@@ -176,7 +179,7 @@ void DeviceContextVkImpl::DisposeVkCmdBuffer(Uint32 CmdQueue, VkCommandBuffer vk
public:
// clang-format off
CmdBufferDeleter(VkCommandBuffer _vkCmdBuff,
- VulkanUtilities::VulkanCommandBufferPool& _Pool) noexcept :
+ VulkanUtilities::VulkanCommandBufferPool& _Pool) noexcept :
vkCmdBuff {_vkCmdBuff},
Pool {&_Pool }
{
@@ -231,9 +234,11 @@ void DeviceContextVkImpl::SetPipelineState(IPipelineState* pPipelineState)
if (PipelineStateVkImpl::IsSameObject(m_pPipelineState, pPipelineStateVk))
return;
- // Never flush deferred context!
- // A query must begin and end in the same command buffer (17.2)
- if (!m_bIsDeferred && m_State.NumCommands >= m_NumCommandsToFlush && m_ActiveQueriesCounter == 0)
+ if (m_State.NumCommands >= m_NumCommandsToFlush &&
+ !m_bIsDeferred && // Never flush deferred context
+ !m_pActiveRenderPass && // Never flush inside active render pass (https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#VUID-vkEndCommandBuffer-commandBuffer-00060)
+ m_ActiveQueriesCounter == 0 // A query must begin and end in the same command buffer (17.2)
+ )
{
Flush();
}
@@ -278,7 +283,6 @@ void DeviceContextVkImpl::SetPipelineState(IPipelineState* pPipelineState)
{
m_CommandBuffer.SetStencilReference(m_StencilRef);
m_CommandBuffer.SetBlendConstants(m_BlendFactors);
- CommitRenderPassAndFramebuffer(true);
CommitViewports();
}
@@ -293,7 +297,12 @@ void DeviceContextVkImpl::SetPipelineState(IPipelineState* pPipelineState)
void DeviceContextVkImpl::TransitionShaderResources(IPipelineState* pPipelineState, IShaderResourceBinding* pShaderResourceBinding)
{
- VERIFY_EXPR(pPipelineState != nullptr);
+ DEV_CHECK_ERR(pPipelineState != nullptr, "Pipeline state must mot be null");
+ if (m_pActiveRenderPass)
+ {
+ LOG_ERROR_MESSAGE("State transitions are not allowed inside a render pass.");
+ return;
+ }
auto* pPipelineStateVk = ValidatedCast<PipelineStateVkImpl>(pPipelineState);
pPipelineStateVk->CommitAndTransitionShaderResources(pShaderResourceBinding, this, false, RESOURCE_STATE_TRANSITION_MODE_TRANSITION, nullptr);
@@ -417,6 +426,9 @@ void DeviceContextVkImpl::PrepareForDraw(DRAW_FLAGS Flags)
#ifdef DILIGENT_DEVELOPMENT
if ((Flags & DRAW_FLAG_VERIFY_RENDER_TARGETS) != 0)
DvpVerifyRenderTargets();
+
+ VERIFY(m_vkRenderPass != VK_NULL_HANDLE, "No render pass is active while executing draw command");
+ VERIFY(m_vkFramebuffer != VK_NULL_HANDLE, "No framebuffer is bound while executing draw command");
#endif
EnsureVkCmdBuffer();
@@ -460,14 +472,19 @@ void DeviceContextVkImpl::PrepareForDraw(DRAW_FLAGS Flags)
# endif
#endif
-#ifdef DILIGENT_DEVELOPMENT
- if (m_pPipelineState->GetVkRenderPass() != m_RenderPass)
+ if (m_pPipelineState->GetDesc().GraphicsPipeline.pRenderPass == nullptr)
{
- DvpLogRenderPass_PSOMismatch();
- }
+#ifdef DILIGENT_DEVELOPMENT
+ if (m_pPipelineState->GetRenderPass()->GetVkRenderPass() != m_vkRenderPass)
+ {
+ // Note that different Vulkan render passes may still be compatible,
+ // so we should only verify implicit render passes
+ DvpLogRenderPass_PSOMismatch();
+ }
#endif
- CommitRenderPassAndFramebuffer((Flags & DRAW_FLAG_VERIFY_STATES) != 0);
+ CommitRenderPassAndFramebuffer((Flags & DRAW_FLAG_VERIFY_STATES) != 0);
+ }
}
BufferVkImpl* DeviceContextVkImpl::PrepareIndirectDrawAttribsBuffer(IBuffer* pAttribsBuffer, RESOURCE_STATE_TRANSITION_MODE TransitonMode)
@@ -631,13 +648,21 @@ void DeviceContextVkImpl::ClearDepthStencil(ITextureView* pView
const auto& ViewDesc = pVkDSV->GetDesc();
VERIFY(ViewDesc.TextureDim != RESOURCE_DIM_TEX_3D, "Depth-stencil view of a 3D texture should've been created as 2D texture array view");
- if (pVkDSV == m_pBoundDepthStencil)
+ bool ClearAsAttachment = pVkDSV == m_pBoundDepthStencil;
+ VERIFY(m_pActiveRenderPass == nullptr || ClearAsAttachment,
+ "DSV was not found in the framebuffer. This is unexpected because TDeviceContextBase::ClearDepthStencil "
+ "checks if the DSV is bound as a framebuffer attachment and returns false otherwise (in development mode).");
+ if (ClearAsAttachment)
{
- // Render pass may not be currently committed
- VERIFY_EXPR(m_RenderPass != VK_NULL_HANDLE && m_Framebuffer != VK_NULL_HANDLE);
- TransitionRenderTargets(StateTransitionMode);
- // No need to verify states again
- CommitRenderPassAndFramebuffer(false);
+ VERIFY_EXPR(m_vkRenderPass != VK_NULL_HANDLE && m_vkFramebuffer != VK_NULL_HANDLE);
+ if (m_pActiveRenderPass == nullptr)
+ {
+ // Render pass may not be currently committed
+
+ TransitionRenderTargets(StateTransitionMode);
+ // No need to verify states again
+ CommitRenderPassAndFramebuffer(false);
+ }
VkClearAttachment ClearAttachment = {};
ClearAttachment.aspectMask = 0;
@@ -732,7 +757,7 @@ void DeviceContextVkImpl::ClearRenderTarget(ITextureView* pView, const float* RG
VERIFY(ViewDesc.TextureDim != RESOURCE_DIM_TEX_3D, "Render target view of a 3D texture should've been created as 2D texture array view");
// Check if the texture is one of the currently bound render targets
- static constexpr const Uint32 InvalidAttachmentIndex = static_cast<Uint32>(-1);
+ static constexpr const Uint32 InvalidAttachmentIndex = ~Uint32{0};
Uint32 attachmentIndex = InvalidAttachmentIndex;
for (Uint32 rt = 0; rt < m_NumBoundRenderTargets; ++rt)
@@ -744,13 +769,21 @@ void DeviceContextVkImpl::ClearRenderTarget(ITextureView* pView, const float* RG
}
}
+ VERIFY(m_pActiveRenderPass == nullptr || attachmentIndex != InvalidAttachmentIndex,
+ "Render target was not found in the framebuffer. This is unexpected because TDeviceContextBase::ClearRenderTarget "
+ "checks if the RTV is bound as a framebuffer attachment and returns false otherwise (in development mode).");
+
if (attachmentIndex != InvalidAttachmentIndex)
{
- // Render pass may not be currently committed
- VERIFY_EXPR(m_RenderPass != VK_NULL_HANDLE && m_Framebuffer != VK_NULL_HANDLE);
- TransitionRenderTargets(StateTransitionMode);
- // No need to verify states again
- CommitRenderPassAndFramebuffer(false);
+ VERIFY_EXPR(m_vkRenderPass != VK_NULL_HANDLE && m_vkFramebuffer != VK_NULL_HANDLE);
+ if (m_pActiveRenderPass == nullptr)
+ {
+ // Render pass may not be currently committed
+
+ TransitionRenderTargets(StateTransitionMode);
+ // No need to verify states again
+ CommitRenderPassAndFramebuffer(false);
+ }
VkClearAttachment ClearAttachment = {};
ClearAttachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
@@ -773,6 +806,8 @@ void DeviceContextVkImpl::ClearRenderTarget(ITextureView* pView, const float* RG
}
else
{
+ VERIFY(m_pActiveRenderPass == nullptr, "This branch should never execute inside a render pass.");
+
// End current render pass and clear the image with vkCmdClearColorImage
if (m_CommandBuffer.GetState().RenderPass != VK_NULL_HANDLE)
m_CommandBuffer.EndRenderPass();
@@ -837,6 +872,11 @@ void DeviceContextVkImpl::FinishFrame()
"All queries must be ended before the frame is finished.");
}
+ if (m_pActiveRenderPass != nullptr)
+ {
+ LOG_ERROR_MESSAGE("Finishing frame inside an active render pass.");
+ }
+
if (!m_MappedTextures.empty())
LOG_ERROR_MESSAGE("There are mapped textures in the device context when finishing the frame. All dynamic resources must be used in the same frame in which they are mapped.");
@@ -866,14 +906,19 @@ void DeviceContextVkImpl::Flush()
{
if (m_bIsDeferred)
{
- LOG_ERROR_MESSAGE("Flush() should only be called for immediate contexts");
+ LOG_ERROR_MESSAGE("Flush() should only be called for immediate contexts.");
return;
}
if (m_ActiveQueriesCounter > 0)
{
LOG_ERROR_MESSAGE("Flushing device context that has ", m_ActiveQueriesCounter,
- " active queries. Vulkan requires that queries are begun and ended in the same command buffer");
+ " active queries. Vulkan requires that queries are begun and ended in the same command buffer.");
+ }
+
+ if (m_pActiveRenderPass != nullptr)
+ {
+ LOG_ERROR_MESSAGE("Flushing device context inside an active render pass.");
}
VkSubmitInfo SubmitInfo = {};
@@ -933,7 +978,9 @@ void DeviceContextVkImpl::Flush()
m_State = ContextState{};
m_DescrSetBindInfo.Reset();
m_CommandBuffer.Reset();
- m_pPipelineState = nullptr;
+ m_pPipelineState = nullptr;
+ m_pActiveRenderPass = nullptr;
+ m_pBoundFramebuffer = nullptr;
}
void DeviceContextVkImpl::SetVertexBuffers(Uint32 StartSlot,
@@ -962,9 +1009,9 @@ void DeviceContextVkImpl::InvalidateState()
LOG_WARNING_MESSAGE("Invalidating context that has outstanding commands in it. Call Flush() to submit commands for execution");
TDeviceContextBase::InvalidateState();
- m_State = ContextState{};
- m_RenderPass = VK_NULL_HANDLE;
- m_Framebuffer = VK_NULL_HANDLE;
+ m_State = ContextState{};
+ m_vkRenderPass = VK_NULL_HANDLE;
+ m_vkFramebuffer = VK_NULL_HANDLE;
m_DescrSetBindInfo.Reset();
VERIFY(m_CommandBuffer.GetState().RenderPass == VK_NULL_HANDLE, "Invalidating context with unifinished render pass");
m_CommandBuffer.Reset();
@@ -1078,6 +1125,9 @@ void DeviceContextVkImpl::SetScissorRects(Uint32 NumRects, const Rect* pRects, U
void DeviceContextVkImpl::TransitionRenderTargets(RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
{
+ VERIFY(StateTransitionMode != RESOURCE_STATE_TRANSITION_MODE_TRANSITION || m_pActiveRenderPass == nullptr,
+ "State transitions are not allowed inside a render pass.");
+
if (m_pBoundDepthStencil)
{
auto* pDepthBufferVk = ValidatedCast<TextureVkImpl>(m_pBoundDepthStencil->GetTexture());
@@ -1098,22 +1148,24 @@ void DeviceContextVkImpl::TransitionRenderTargets(RESOURCE_STATE_TRANSITION_MODE
void DeviceContextVkImpl::CommitRenderPassAndFramebuffer(bool VerifyStates)
{
+ VERIFY(m_pActiveRenderPass == nullptr, "This method must not be called inside an active render pass.");
+
const auto& CmdBufferState = m_CommandBuffer.GetState();
- if (CmdBufferState.Framebuffer != m_Framebuffer)
+ if (CmdBufferState.Framebuffer != m_vkFramebuffer)
{
if (CmdBufferState.RenderPass != VK_NULL_HANDLE)
m_CommandBuffer.EndRenderPass();
- if (m_Framebuffer != VK_NULL_HANDLE)
+ if (m_vkFramebuffer != VK_NULL_HANDLE)
{
- VERIFY_EXPR(m_RenderPass != VK_NULL_HANDLE);
+ VERIFY_EXPR(m_vkRenderPass != VK_NULL_HANDLE);
#ifdef DILIGENT_DEVELOPMENT
if (VerifyStates)
{
TransitionRenderTargets(RESOURCE_STATE_TRANSITION_MODE_VERIFY);
}
#endif
- m_CommandBuffer.BeginRenderPass(m_RenderPass, m_Framebuffer, m_FramebufferWidth, m_FramebufferHeight);
+ m_CommandBuffer.BeginRenderPass(m_vkRenderPass, m_vkFramebuffer, m_FramebufferWidth, m_FramebufferHeight);
}
}
}
@@ -1123,6 +1175,14 @@ void DeviceContextVkImpl::SetRenderTargets(Uint32 NumRen
ITextureView* pDepthStencil,
RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
{
+#ifdef DILIGENT_DEVELOPMENT
+ if (m_pActiveRenderPass != nullptr)
+ {
+ LOG_ERROR_MESSAGE("Calling SetRenderTargets inside active render pass is invalid. End the render pass first");
+ return;
+ }
+#endif
+
if (TDeviceContextBase::SetRenderTargets(NumRenderTargets, ppRenderTargets, pDepthStencil))
{
FramebufferCache::FramebufferCacheKey FBKey;
@@ -1163,12 +1223,12 @@ void DeviceContextVkImpl::SetRenderTargets(Uint32 NumRen
}
auto& FBCache = m_pDevice->GetFramebufferCache();
- auto& RPCache = m_pDevice->GetRenderPassCache();
+ auto& RPCache = m_pDevice->GetImplicitRenderPassCache();
- m_RenderPass = RPCache.GetRenderPass(RenderPassKey);
- FBKey.Pass = m_RenderPass;
+ m_vkRenderPass = RPCache.GetRenderPass(RenderPassKey)->GetVkRenderPass();
+ FBKey.Pass = m_vkRenderPass;
FBKey.CommandQueueMask = ~Uint64{0};
- m_Framebuffer = FBCache.GetFramebuffer(FBKey, m_FramebufferWidth, m_FramebufferHeight, m_FramebufferSlices);
+ m_vkFramebuffer = FBCache.GetFramebuffer(FBKey, m_FramebufferWidth, m_FramebufferHeight, m_FramebufferSlices);
// Set the viewport to match the render target size
SetViewports(1, nullptr, 0, 0);
@@ -1184,12 +1244,81 @@ void DeviceContextVkImpl::SetRenderTargets(Uint32 NumRen
void DeviceContextVkImpl::ResetRenderTargets()
{
TDeviceContextBase::ResetRenderTargets();
- m_RenderPass = VK_NULL_HANDLE;
- m_Framebuffer = VK_NULL_HANDLE;
+ m_vkRenderPass = VK_NULL_HANDLE;
+ m_vkFramebuffer = VK_NULL_HANDLE;
if (m_CommandBuffer.GetVkCmdBuffer() != VK_NULL_HANDLE && m_CommandBuffer.GetState().RenderPass != VK_NULL_HANDLE)
m_CommandBuffer.EndRenderPass();
}
+void DeviceContextVkImpl::BeginRenderPass(const BeginRenderPassAttribs& Attribs)
+{
+ TDeviceContextBase::BeginRenderPass(Attribs);
+
+ VERIFY_EXPR(m_pActiveRenderPass != nullptr);
+ VERIFY_EXPR(m_pBoundFramebuffer != nullptr);
+ VERIFY_EXPR(m_vkRenderPass == VK_NULL_HANDLE);
+ VERIFY_EXPR(m_vkFramebuffer == VK_NULL_HANDLE);
+
+ m_vkRenderPass = m_pActiveRenderPass->GetVkRenderPass();
+ m_vkFramebuffer = m_pBoundFramebuffer->GetVkFramebuffer();
+
+ VkClearValue* pVkClearValues = nullptr;
+ if (Attribs.ClearValueCount > 0)
+ {
+ m_vkClearValues.resize(Attribs.ClearValueCount);
+ const auto& RPDesc = m_pActiveRenderPass->GetDesc();
+ for (Uint32 i = 0; i < std::min(RPDesc.AttachmentCount, Attribs.ClearValueCount); ++i)
+ {
+ const auto& ClearVal = Attribs.pClearValues[i];
+ auto& vkClearVal = m_vkClearValues[i];
+
+ const auto& FmtAttribs = GetTextureFormatAttribs(RPDesc.pAttachments[i].Format);
+ if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH ||
+ FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL)
+ {
+ vkClearVal.depthStencil.depth = ClearVal.DepthStencil.Depth;
+ vkClearVal.depthStencil.stencil = ClearVal.DepthStencil.Stencil;
+ }
+ else
+ {
+ vkClearVal.color.float32[0] = ClearVal.Color[0];
+ vkClearVal.color.float32[1] = ClearVal.Color[1];
+ vkClearVal.color.float32[2] = ClearVal.Color[2];
+ vkClearVal.color.float32[3] = ClearVal.Color[3];
+ }
+ }
+ pVkClearValues = m_vkClearValues.data();
+ }
+
+ EnsureVkCmdBuffer();
+ m_CommandBuffer.BeginRenderPass(m_vkRenderPass, m_vkFramebuffer, m_FramebufferWidth, m_FramebufferHeight, Attribs.ClearValueCount, pVkClearValues);
+
+ // Set the viewport to match the framebuffer size
+ SetViewports(1, nullptr, 0, 0);
+}
+
+void DeviceContextVkImpl::NextSubpass()
+{
+ TDeviceContextBase::NextSubpass();
+ VERIFY_EXPR(m_CommandBuffer.GetVkCmdBuffer() != VK_NULL_HANDLE && m_CommandBuffer.GetState().RenderPass != VK_NULL_HANDLE);
+ m_CommandBuffer.NextSubpass();
+}
+
+void DeviceContextVkImpl::EndRenderPass()
+{
+ TDeviceContextBase::EndRenderPass();
+ // TDeviceContextBase::EndRenderPass calls ResetRenderTargets() that in turn
+ // calls m_CommandBuffer.EndRenderPass()
+
+ if (m_State.NumCommands >= m_NumCommandsToFlush &&
+ !m_bIsDeferred && // Never flush deferred context
+ m_ActiveQueriesCounter == 0 // A query must begin and end in the same command buffer (17.2)
+ )
+ {
+ Flush();
+ }
+}
+
void DeviceContextVkImpl::UpdateBufferRegion(BufferVkImpl* pBuffVk,
Uint64 DstOffset,
Uint64 NumBytes,
@@ -1948,6 +2077,8 @@ void DeviceContextVkImpl::UnmapTextureSubresource(ITexture* pTexture,
void DeviceContextVkImpl::FinishCommandList(class ICommandList** ppCommandList)
{
+ VERIFY(m_pActiveRenderPass == nullptr, "Finishing command list inside an active render pass.");
+
if (m_CommandBuffer.GetState().RenderPass != VK_NULL_HANDLE)
{
m_CommandBuffer.EndRenderPass();
@@ -2112,6 +2243,7 @@ void DeviceContextVkImpl::EndQuery(IQuery* pQuery)
void DeviceContextVkImpl::TransitionImageLayout(ITexture* pTexture, VkImageLayout NewLayout)
{
VERIFY_EXPR(pTexture != nullptr);
+ VERIFY(m_pActiveRenderPass == nullptr, "State transitions are not allowed inside a render pass");
auto pTextureVk = ValidatedCast<TextureVkImpl>(pTexture);
if (!pTextureVk->IsInKnownState())
{
@@ -2131,6 +2263,7 @@ void DeviceContextVkImpl::TransitionTextureState(TextureVkImpl& Textur
bool UpdateTextureState,
VkImageSubresourceRange* pSubresRange /* = nullptr*/)
{
+ VERIFY(m_pActiveRenderPass == nullptr, "State transitions are not allowed inside a render pass");
if (OldState == RESOURCE_STATE_UNKNOWN)
{
if (TextureVk.IsInKnownState())
@@ -2206,6 +2339,7 @@ void DeviceContextVkImpl::TransitionOrVerifyTextureState(TextureVkImpl&
{
if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
{
+ VERIFY(m_pActiveRenderPass == nullptr, "State transitions are not allowed inside a render pass");
if (Texture.IsInKnownState())
{
if (!Texture.CheckState(RequiredState))
@@ -2253,6 +2387,7 @@ void DeviceContextVkImpl::BufferMemoryBarrier(IBuffer* pBuffer, VkAccessFlags Ne
void DeviceContextVkImpl::TransitionBufferState(BufferVkImpl& BufferVk, RESOURCE_STATE OldState, RESOURCE_STATE NewState, bool UpdateBufferState)
{
+ VERIFY(m_pActiveRenderPass == nullptr, "State transitions are not allowed inside a render pass");
if (OldState == RESOURCE_STATE_UNKNOWN)
{
if (BufferVk.IsInKnownState())
@@ -2302,6 +2437,7 @@ void DeviceContextVkImpl::TransitionOrVerifyBufferState(BufferVkImpl&
{
if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
{
+ VERIFY(m_pActiveRenderPass == nullptr, "State transitions are not allowed inside a render pass");
if (Buffer.IsInKnownState())
{
if (!Buffer.CheckState(RequiredState))
@@ -2330,6 +2466,8 @@ VulkanDynamicAllocation DeviceContextVkImpl::AllocateDynamicSpace(Uint32 SizeInB
void DeviceContextVkImpl::TransitionResourceStates(Uint32 BarrierCount, StateTransitionDesc* pResourceBarriers)
{
+ VERIFY(m_pActiveRenderPass == nullptr, "State transitions are not allowed inside a render pass");
+
if (BarrierCount == 0)
return;
diff --git a/Graphics/GraphicsEngineVulkan/src/FramebufferVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/FramebufferVkImpl.cpp
new file mode 100644
index 00000000..54b77e36
--- /dev/null
+++ b/Graphics/GraphicsEngineVulkan/src/FramebufferVkImpl.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2019-2020 Diligent Graphics LLC
+ * Copyright 2015-2019 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+#include <vector>
+
+#include "FramebufferVkImpl.hpp"
+#include "EngineMemory.h"
+#include "RenderPassVkImpl.hpp"
+#include "TextureViewVkImpl.hpp"
+
+namespace Diligent
+{
+
+FramebufferVkImpl::FramebufferVkImpl(IReferenceCounters* pRefCounters,
+ RenderDeviceVkImpl* pDevice,
+ const FramebufferDesc& Desc) :
+ TFramebufferBase{pRefCounters, pDevice, Desc}
+{
+ VkFramebufferCreateInfo FramebufferCI = {};
+
+ FramebufferCI.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+ FramebufferCI.pNext = nullptr;
+ FramebufferCI.flags = 0;
+
+ auto* pRenderPassVkImpl = ValidatedCast<RenderPassVkImpl>(m_Desc.pRenderPass);
+ FramebufferCI.renderPass = pRenderPassVkImpl->GetVkRenderPass();
+
+ FramebufferCI.attachmentCount = m_Desc.AttachmentCount;
+
+ std::vector<VkImageView> vkImgViews(m_Desc.AttachmentCount);
+ for (Uint32 i = 0; i < m_Desc.AttachmentCount; ++i)
+ {
+ if (auto* pView = m_Desc.ppAttachments[i])
+ {
+ vkImgViews[i] = ValidatedCast<TextureViewVkImpl>(pView)->GetVulkanImageView();
+ }
+ }
+ FramebufferCI.pAttachments = vkImgViews.data();
+
+ FramebufferCI.width = m_Desc.Width;
+ FramebufferCI.height = m_Desc.Height;
+ FramebufferCI.layers = m_Desc.NumArraySlices;
+
+ const auto& LogicalDevice = pDevice->GetLogicalDevice();
+
+ m_VkFramebuffer = LogicalDevice.CreateFramebuffer(FramebufferCI, m_Desc.Name);
+ if (!m_VkFramebuffer)
+ {
+ LOG_ERROR_AND_THROW("Failed to create Vulkan framebuffer");
+ }
+}
+
+FramebufferVkImpl::~FramebufferVkImpl()
+{
+ m_pDevice->SafeReleaseDeviceObject(std::move(m_VkFramebuffer), ~Uint64{0});
+}
+
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp
index 32a68780..aa027b25 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp
@@ -64,7 +64,7 @@ class ResourceTypeToVkDescriptorType
public:
ResourceTypeToVkDescriptorType()
{
- static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 10, "Please add corresponding decriptor type");
+ 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;
@@ -75,6 +75,7 @@ public:
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;
}
VkDescriptorType operator[](SPIRVShaderResourceAttribs::ResourceType ResType) const
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
index 99b27d2c..96592793 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
@@ -32,10 +32,12 @@
#include "VulkanTypeConversions.hpp"
#include "RenderDeviceVkImpl.hpp"
#include "DeviceContextVkImpl.hpp"
+#include "RenderPassVkImpl.hpp"
#include "ShaderResourceBindingVkImpl.hpp"
#include "EngineMemory.h"
#include "StringTools.hpp"
+
#if !DILIGENT_NO_HLSL
# include "spirv-tools/optimizer.hpp"
#endif
@@ -43,97 +45,88 @@
namespace Diligent
{
-VkRenderPassCreateInfo PipelineStateVkImpl::GetRenderPassCreateInfo(
- Uint32 NumRenderTargets,
- const TEXTURE_FORMAT RTVFormats[],
- TEXTURE_FORMAT DSVFormat,
- Uint32 SampleCount,
- std::array<VkAttachmentDescription, MAX_RENDER_TARGETS + 1>& Attachments,
- std::array<VkAttachmentReference, MAX_RENDER_TARGETS + 1>& AttachmentReferences,
- VkSubpassDescription& SubpassDesc)
+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);
- // Prepare render pass create info (7.1)
- VkRenderPassCreateInfo RenderPassCI = {};
+ RenderPassDesc RPDesc;
- RenderPassCI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
- RenderPassCI.pNext = nullptr;
- RenderPassCI.flags = 0; // reserved for future use
- RenderPassCI.attachmentCount = (DSVFormat != TEX_FORMAT_UNKNOWN ? 1 : 0) + NumRenderTargets;
+ RPDesc.AttachmentCount = (DSVFormat != TEX_FORMAT_UNKNOWN ? 1 : 0) + NumRenderTargets;
- uint32_t AttachmentInd = 0;
- VkSampleCountFlagBits SampleCountFlags = static_cast<VkSampleCountFlagBits>(SampleCount);
- VkAttachmentReference* pDepthAttachmentReference = nullptr;
+ uint32_t AttachmentInd = 0;
+ AttachmentReference* pDepthAttachmentReference = nullptr;
if (DSVFormat != TEX_FORMAT_UNKNOWN)
{
auto& DepthAttachment = Attachments[AttachmentInd];
- DepthAttachment.flags = 0; // Allowed value VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT
- DepthAttachment.format = TexFormatToVkFormat(DSVFormat);
- DepthAttachment.samples = SampleCountFlags;
- DepthAttachment.loadOp = VK_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 = VK_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 = VK_ATTACHMENT_LOAD_OP_LOAD;
- DepthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
- DepthAttachment.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
- DepthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
-
- pDepthAttachmentReference = &AttachmentReferences[AttachmentInd];
- pDepthAttachmentReference->attachment = AttachmentInd;
- pDepthAttachmentReference->layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+ 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;
}
- VkAttachmentReference* pColorAttachmentsReference = NumRenderTargets > 0 ? &AttachmentReferences[AttachmentInd] : nullptr;
+ AttachmentReference* pColorAttachmentsReference = NumRenderTargets > 0 ? &AttachmentReferences[AttachmentInd] : nullptr;
for (Uint32 rt = 0; rt < NumRenderTargets; ++rt, ++AttachmentInd)
{
auto& ColorAttachment = Attachments[AttachmentInd];
- ColorAttachment.flags = 0; // Allowed value VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT
- ColorAttachment.format = TexFormatToVkFormat(RTVFormats[rt]);
- ColorAttachment.samples = SampleCountFlags;
- ColorAttachment.loadOp = VK_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 = VK_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 = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- ColorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- ColorAttachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- ColorAttachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
-
- auto& ColorAttachmentRef = AttachmentReferences[AttachmentInd];
- ColorAttachmentRef.attachment = AttachmentInd;
- ColorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ 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;
}
- RenderPassCI.pAttachments = Attachments.data();
- RenderPassCI.subpassCount = 1;
- RenderPassCI.pSubpasses = &SubpassDesc;
- RenderPassCI.dependencyCount = 0; // the number of dependencies between pairs of subpasses, or zero indicating no dependencies.
- RenderPassCI.pDependencies = nullptr; // an array of dependencyCount number of VkSubpassDependency structures describing
- // dependencies between pairs of subpasses, or NULL if dependencyCount is zero.
-
-
- SubpassDesc.flags = 0; // All bits for this type are defined by extensions
- SubpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; // Currently, only graphics subpasses are supported.
- SubpassDesc.inputAttachmentCount = 0;
- SubpassDesc.pInputAttachments = nullptr;
- SubpassDesc.colorAttachmentCount = NumRenderTargets;
- SubpassDesc.pColorAttachments = pColorAttachmentsReference;
- SubpassDesc.pResolveAttachments = nullptr;
- SubpassDesc.pDepthStencilAttachment = pDepthAttachmentReference;
- SubpassDesc.preserveAttachmentCount = 0;
- SubpassDesc.pPreserveAttachments = nullptr;
-
- return RenderPassCI;
+ 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 std::vector<uint32_t> StripReflection(const std::vector<uint32_t>& OriginalSPIRV)
@@ -295,14 +288,17 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCoun
{
const auto& PhysicalDevice = pDeviceVk->GetPhysicalDevice();
auto& GraphicsPipeline = m_Desc.GraphicsPipeline;
- auto& RPCache = pDeviceVk->GetRenderPassCache();
+ auto& RPCache = pDeviceVk->GetImplicitRenderPassCache();
- RenderPassCache::RenderPassCacheKey Key{
- GraphicsPipeline.NumRenderTargets,
- GraphicsPipeline.SmplDesc.Count,
- GraphicsPipeline.RTVFormats,
- GraphicsPipeline.DSVFormat};
- m_RenderPass = RPCache.GetRenderPass(Key);
+ if (m_pRenderPass == nullptr)
+ {
+ RenderPassCache::RenderPassCacheKey Key{
+ GraphicsPipeline.NumRenderTargets,
+ GraphicsPipeline.SmplDesc.Count,
+ GraphicsPipeline.RTVFormats,
+ GraphicsPipeline.DSVFormat};
+ m_pRenderPass = RPCache.GetRenderPass(Key);
+ }
VkGraphicsPipelineCreateInfo PipelineCI = {};
@@ -398,13 +394,16 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCoun
DepthStencilStateDesc_To_VkDepthStencilStateCI(GraphicsPipeline.DepthStencilDesc);
PipelineCI.pDepthStencilState = &DepthStencilStateCI;
- std::vector<VkPipelineColorBlendAttachmentState> ColorBlendAttachmentStates(m_Desc.GraphicsPipeline.NumRenderTargets);
+ const auto& RPDesc = m_pRenderPass->GetDesc();
+ const auto NumRTAttachments = RPDesc.pSubpasses[GraphicsPipeline.SubpassIndex].RenderTargetAttachmentCount;
+ VERIFY_EXPR(GraphicsPipeline.pRenderPass != nullptr || GraphicsPipeline.NumRenderTargets == NumRTAttachments);
+ std::vector<VkPipelineColorBlendAttachmentState> ColorBlendAttachmentStates(NumRTAttachments);
VkPipelineColorBlendStateCreateInfo BlendStateCI = {};
BlendStateCI.pAttachments = !ColorBlendAttachmentStates.empty() ? ColorBlendAttachmentStates.data() : nullptr;
- BlendStateCI.attachmentCount = m_Desc.GraphicsPipeline.NumRenderTargets; // must equal the colorAttachmentCount for the subpass
- // in which this pipeline is used.
+ BlendStateCI.attachmentCount = NumRTAttachments; // must equal the colorAttachmentCount for the subpass
+ // in which this pipeline is used.
BlendStateDesc_To_VkBlendStateCI(GraphicsPipeline.BlendDesc, BlendStateCI, ColorBlendAttachmentStates);
PipelineCI.pColorBlendState = &BlendStateCI;
@@ -442,8 +441,8 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCoun
PipelineCI.pDynamicState = &DynamicStateCI;
- PipelineCI.renderPass = m_RenderPass;
- PipelineCI.subpass = 0;
+ PipelineCI.renderPass = GetRenderPass()->GetVkRenderPass();
+ PipelineCI.subpass = m_Desc.GraphicsPipeline.SubpassIndex;
PipelineCI.basePipelineHandle = VK_NULL_HANDLE; // a pipeline to derive from
PipelineCI.basePipelineIndex = 0; // an index into the pCreateInfos parameter to use as a pipeline to derive from
diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
index 4e6049b0..18814e06 100644
--- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
@@ -37,6 +37,8 @@
#include "DeviceContextVkImpl.hpp"
#include "FenceVkImpl.hpp"
#include "QueryVkImpl.hpp"
+#include "RenderPassVkImpl.hpp"
+#include "FramebufferVkImpl.hpp"
#include "EngineMemory.h"
namespace Diligent
@@ -71,15 +73,17 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters*
sizeof(PipelineStateVkImpl),
sizeof(ShaderResourceBindingVkImpl),
sizeof(FenceVkImpl),
- sizeof(QueryVkImpl)
+ sizeof(QueryVkImpl),
+ sizeof(RenderPassVkImpl),
+ sizeof(FramebufferVkImpl)
}
},
- m_VulkanInstance {Instance },
- m_PhysicalDevice {std::move(PhysicalDevice)},
- m_LogicalVkDevice {std::move(LogicalDevice) },
- m_EngineAttribs {EngineCI },
- m_FramebufferCache {*this },
- m_RenderPassCache {*this },
+ m_VulkanInstance {Instance },
+ m_PhysicalDevice {std::move(PhysicalDevice)},
+ m_LogicalVkDevice {std::move(LogicalDevice) },
+ m_EngineAttribs {EngineCI },
+ m_FramebufferCache {*this },
+ m_ImplicitRenderPassCache{*this },
m_DescriptorSetAllocator
{
*this,
@@ -207,6 +211,9 @@ RenderDeviceVkImpl::~RenderDeviceVkImpl()
// the heap into release queues
m_DynamicMemoryManager.Destroy();
+ // Explicitly destroy render pass cache
+ m_ImplicitRenderPassCache.Destroy();
+
// Wait for the GPU to complete all its operations
IdleGPU();
@@ -618,4 +625,35 @@ void RenderDeviceVkImpl::CreateQuery(const QueryDesc& Desc, IQuery** ppQuery)
);
}
+void RenderDeviceVkImpl::CreateRenderPass(const RenderPassDesc& Desc,
+ IRenderPass** ppRenderPass,
+ bool IsDeviceInternal)
+{
+ CreateDeviceObject(
+ "RenderPass", Desc, ppRenderPass,
+ [&]() //
+ {
+ RenderPassVkImpl* pRenderPassVk(NEW_RC_OBJ(m_RenderPassAllocator, "RenderPassVkImpl instance", RenderPassVkImpl)(this, Desc, IsDeviceInternal));
+ pRenderPassVk->QueryInterface(IID_RenderPass, reinterpret_cast<IObject**>(ppRenderPass));
+ OnCreateDeviceObject(pRenderPassVk);
+ } //
+ );
+}
+
+void RenderDeviceVkImpl::CreateRenderPass(const RenderPassDesc& Desc, IRenderPass** ppRenderPass)
+{
+ CreateRenderPass(Desc, ppRenderPass, /*IsDeviceInternal = */ false);
+}
+
+void RenderDeviceVkImpl::CreateFramebuffer(const FramebufferDesc& Desc, IFramebuffer** ppFramebuffer)
+{
+ CreateDeviceObject("Framebuffer", Desc, ppFramebuffer,
+ [&]() //
+ {
+ FramebufferVkImpl* pFramebufferVk(NEW_RC_OBJ(m_FramebufferAllocator, "FramebufferVkImpl instance", FramebufferVkImpl)(this, Desc));
+ pFramebufferVk->QueryInterface(IID_Framebuffer, reinterpret_cast<IObject**>(ppFramebuffer));
+ OnCreateDeviceObject(pFramebufferVk);
+ });
+}
+
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/RenderPassCache.cpp b/Graphics/GraphicsEngineVulkan/src/RenderPassCache.cpp
index c352c2a9..a40010f1 100644
--- a/Graphics/GraphicsEngineVulkan/src/RenderPassCache.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/RenderPassCache.cpp
@@ -30,36 +30,52 @@
#include "RenderPassCache.hpp"
#include "RenderDeviceVkImpl.hpp"
#include "PipelineStateVkImpl.hpp"
+#include "RenderPassVkImpl.hpp"
namespace Diligent
{
+RenderPassCache::RenderPassCache(RenderDeviceVkImpl& DeviceVk) noexcept :
+ m_DeviceVkImpl{DeviceVk}
+{}
+
+
RenderPassCache::~RenderPassCache()
{
+ // Render pass cache is part of the render device, so we can't release
+ // render pass objects from here as their destructors will attmept to
+ // call SafeReleaseDeviceObject.
+ VERIFY(m_Cache.empty(), "Render pass cache is not empty. Did you call Destroy?");
+}
+
+void RenderPassCache::Destroy()
+{
auto& FBCache = m_DeviceVkImpl.GetFramebufferCache();
for (auto it = m_Cache.begin(); it != m_Cache.end(); ++it)
{
- FBCache.OnDestroyRenderPass(it->second);
+ FBCache.OnDestroyRenderPass(it->second->GetVkRenderPass());
}
+ m_Cache.clear();
}
-VkRenderPass RenderPassCache::GetRenderPass(const RenderPassCacheKey& Key)
+
+RenderPassVkImpl* RenderPassCache::GetRenderPass(const RenderPassCacheKey& Key)
{
std::lock_guard<std::mutex> Lock{m_Mutex};
auto it = m_Cache.find(Key);
if (it == m_Cache.end())
{
// Do not zero-intitialize arrays
- std::array<VkAttachmentDescription, MAX_RENDER_TARGETS + 1> Attachments;
- std::array<VkAttachmentReference, MAX_RENDER_TARGETS + 1> AttachmentReferences;
+ std::array<RenderPassAttachmentDesc, MAX_RENDER_TARGETS + 1> Attachments;
+ std::array<AttachmentReference, MAX_RENDER_TARGETS + 1> AttachmentReferences;
- VkSubpassDescription Subpass;
+ SubpassDesc Subpass;
- auto RenderPassCI =
- PipelineStateVkImpl::GetRenderPassCreateInfo(Key.NumRenderTargets, Key.RTVFormats, Key.DSVFormat,
- Key.SampleCount, Attachments, AttachmentReferences, Subpass);
+ auto RPDesc =
+ PipelineStateVkImpl::GetImplicitRenderPassDesc(Key.NumRenderTargets, Key.RTVFormats, Key.DSVFormat,
+ Key.SampleCount, Attachments, AttachmentReferences, Subpass);
std::stringstream PassNameSS;
- PassNameSS << "Render pass: RT count: " << Uint32{Key.NumRenderTargets} << "; sample count: " << Uint32{Key.SampleCount}
+ PassNameSS << "Implicit render pass: RT count: " << Uint32{Key.NumRenderTargets} << "; sample count: " << Uint32{Key.SampleCount}
<< "; DSV Format: " << GetTextureFormatAttribs(Key.DSVFormat).Name;
if (Key.NumRenderTargets > 0)
{
@@ -69,9 +85,11 @@ VkRenderPass RenderPassCache::GetRenderPass(const RenderPassCacheKey& Key)
PassNameSS << (rt > 0 ? ", " : "") << GetTextureFormatAttribs(Key.RTVFormats[rt]).Name;
}
}
- auto RenderPass = m_DeviceVkImpl.GetLogicalDevice().CreateRenderPass(RenderPassCI, PassNameSS.str().c_str());
- VERIFY_EXPR(RenderPass != VK_NULL_HANDLE);
- it = m_Cache.emplace(Key, std::move(RenderPass)).first;
+
+ RefCntAutoPtr<RenderPassVkImpl> pRenderPass;
+ m_DeviceVkImpl.CreateRenderPass(RPDesc, pRenderPass.GetRawDblPtr<IRenderPass>(), /* IsDeviceInternal = */ true);
+ VERIFY_EXPR(pRenderPass != nullptr);
+ it = m_Cache.emplace(Key, std::move(pRenderPass)).first;
}
return it->second;
diff --git a/Graphics/GraphicsEngineVulkan/src/RenderPassVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderPassVkImpl.cpp
new file mode 100644
index 00000000..c010e460
--- /dev/null
+++ b/Graphics/GraphicsEngineVulkan/src/RenderPassVkImpl.cpp
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2019-2020 Diligent Graphics LLC
+ * Copyright 2015-2019 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include <vector>
+
+#include "RenderPassVkImpl.hpp"
+#include "VulkanTypeConversions.hpp"
+
+namespace Diligent
+{
+
+RenderPassVkImpl::RenderPassVkImpl(IReferenceCounters* pRefCounters,
+ RenderDeviceVkImpl* pDevice,
+ const RenderPassDesc& Desc,
+ bool IsDeviceInternal) :
+ TRenderPassBase{pRefCounters, pDevice, Desc, IsDeviceInternal}
+{
+ VkRenderPassCreateInfo RenderPassCI = {};
+
+ RenderPassCI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+ RenderPassCI.pNext = nullptr;
+ RenderPassCI.flags = 0;
+
+ std::vector<VkAttachmentDescription> vkAttachments(m_Desc.AttachmentCount);
+ for (Uint32 i = 0; i < m_Desc.AttachmentCount; ++i)
+ {
+ const auto& Attachment = m_Desc.pAttachments[i];
+ auto& vkAttachment = vkAttachments[i];
+ vkAttachment.flags = 0;
+ vkAttachment.format = TexFormatToVkFormat(Attachment.Format);
+ vkAttachment.samples = static_cast<VkSampleCountFlagBits>(Attachment.SampleCount);
+ vkAttachment.loadOp = AttachmentLoadOpToVkAttachmentLoadOp(Attachment.LoadOp);
+ vkAttachment.storeOp = AttachmentStoreOpToVkAttachmentStoreOp(Attachment.StoreOp);
+ vkAttachment.stencilLoadOp = AttachmentLoadOpToVkAttachmentLoadOp(Attachment.StencilLoadOp);
+ vkAttachment.stencilStoreOp = AttachmentStoreOpToVkAttachmentStoreOp(Attachment.StencilStoreOp);
+ vkAttachment.initialLayout = ResourceStateToVkImageLayout(Attachment.InitialState, /*IsInsideRenderPass = */ false);
+ vkAttachment.finalLayout = ResourceStateToVkImageLayout(Attachment.FinalState, /*IsInsideRenderPass = */ true);
+ }
+ RenderPassCI.attachmentCount = Desc.AttachmentCount;
+ RenderPassCI.pAttachments = vkAttachments.data();
+
+
+ Uint32 TotalAttachmentReferencesCount = 0;
+ Uint32 TotalPreserveAttachmentsCount = 0;
+ CountSubpassAttachmentReferences(Desc, TotalAttachmentReferencesCount, TotalPreserveAttachmentsCount);
+ std::vector<VkAttachmentReference> vkAttachmentReferences(TotalAttachmentReferencesCount);
+ std::vector<Uint32> vkPreserveAttachments(TotalPreserveAttachmentsCount);
+
+ Uint32 CurrAttachmentReferenceInd = 0;
+ Uint32 CurrPreserveAttachmentInd = 0;
+
+ std::vector<VkSubpassDescription> vkSubpasses(Desc.SubpassCount);
+ for (Uint32 i = 0; i < m_Desc.SubpassCount; ++i)
+ {
+ const auto& SubpassDesc = m_Desc.pSubpasses[i];
+ auto& vkSubpass = vkSubpasses[i];
+ vkSubpass.flags = 0;
+ vkSubpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ vkSubpass.inputAttachmentCount = SubpassDesc.InputAttachmentCount;
+
+ auto ConvertAttachmentReferences = [&](Uint32 NumAttachments, const AttachmentReference* pSrcAttachments) //
+ {
+ auto* pCurrVkAttachmentReference = &vkAttachmentReferences[CurrAttachmentReferenceInd];
+ for (Uint32 attachment = 0; attachment < NumAttachments; ++attachment, ++CurrAttachmentReferenceInd)
+ {
+ const auto& AttachmnetRef = pSrcAttachments[attachment];
+
+ vkAttachmentReferences[CurrAttachmentReferenceInd].attachment = AttachmnetRef.AttachmentIndex;
+ vkAttachmentReferences[CurrAttachmentReferenceInd].layout =
+ ResourceStateToVkImageLayout(AttachmnetRef.State, /*IsInsideRenderPass = */ true);
+ }
+
+ return pCurrVkAttachmentReference;
+ };
+
+ if (SubpassDesc.InputAttachmentCount != 0)
+ {
+ vkSubpass.pInputAttachments = ConvertAttachmentReferences(SubpassDesc.InputAttachmentCount, SubpassDesc.pInputAttachments);
+ }
+
+ vkSubpass.colorAttachmentCount = SubpassDesc.RenderTargetAttachmentCount;
+ if (SubpassDesc.RenderTargetAttachmentCount != 0)
+ {
+ vkSubpass.pColorAttachments = ConvertAttachmentReferences(SubpassDesc.RenderTargetAttachmentCount, SubpassDesc.pRenderTargetAttachments);
+ if (SubpassDesc.pResolveAttachments != nullptr)
+ {
+ vkSubpass.pResolveAttachments = ConvertAttachmentReferences(SubpassDesc.RenderTargetAttachmentCount, SubpassDesc.pResolveAttachments);
+ }
+ }
+
+ if (SubpassDesc.pDepthStencilAttachment != nullptr)
+ {
+ vkSubpass.pDepthStencilAttachment = ConvertAttachmentReferences(1, SubpassDesc.pDepthStencilAttachment);
+ }
+
+ vkSubpass.preserveAttachmentCount = SubpassDesc.PreserveAttachmentCount;
+ if (SubpassDesc.PreserveAttachmentCount != 0)
+ {
+ vkSubpass.pPreserveAttachments = &vkPreserveAttachments[CurrPreserveAttachmentInd];
+ for (Uint32 prsv_attachment = 0; prsv_attachment < SubpassDesc.PreserveAttachmentCount; ++prsv_attachment, ++CurrPreserveAttachmentInd)
+ {
+ vkPreserveAttachments[CurrPreserveAttachmentInd] = SubpassDesc.pPreserveAttachments[prsv_attachment];
+ }
+ }
+ }
+ VERIFY_EXPR(CurrAttachmentReferenceInd == vkAttachmentReferences.size());
+ VERIFY_EXPR(CurrPreserveAttachmentInd == vkPreserveAttachments.size());
+ RenderPassCI.subpassCount = Desc.SubpassCount;
+ RenderPassCI.pSubpasses = vkSubpasses.data();
+
+ std::vector<VkSubpassDependency> vkDependencies(Desc.DependencyCount);
+ for (Uint32 i = 0; i < Desc.DependencyCount; ++i)
+ {
+ const auto& DependencyDesc = m_Desc.pDependencies[i];
+ auto& vkDependency = vkDependencies[i];
+ vkDependency.srcSubpass = DependencyDesc.SrcSubpass;
+ vkDependency.dstSubpass = DependencyDesc.DstSubpass;
+ vkDependency.srcStageMask = DependencyDesc.SrcStageMask;
+ vkDependency.dstStageMask = DependencyDesc.DstStageMask;
+ vkDependency.srcAccessMask = DependencyDesc.SrcAccessMask;
+ vkDependency.dstAccessMask = DependencyDesc.DstAccessMask;
+ vkDependency.dependencyFlags = 0;
+ }
+ RenderPassCI.dependencyCount = Desc.DependencyCount;
+ RenderPassCI.pDependencies = vkDependencies.data();
+
+ const auto& LogicalDevice = pDevice->GetLogicalDevice();
+
+ m_VkRenderPass = LogicalDevice.CreateRenderPass(RenderPassCI, Desc.Name);
+ if (!m_VkRenderPass)
+ {
+ LOG_ERROR_AND_THROW("Failed to create Vulkan render pass");
+ }
+}
+
+RenderPassVkImpl::~RenderPassVkImpl()
+{
+ m_pDevice->SafeReleaseDeviceObject(std::move(m_VkRenderPass), ~Uint64{0});
+}
+
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
index 06239703..caf8ffd2 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
@@ -155,6 +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");
switch (Res.Type)
{
case SPIRVShaderResourceAttribs::ResourceType::UniformBuffer:
@@ -312,6 +313,14 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl)
}
break;
+ case SPIRVShaderResourceAttribs::ResourceType::InputAttachment:
+ {
+ // Nothing to do with input attachments - they are transitioned by the render pass.
+ // There is nothing we can validate here - a texture may be in different state at
+ // the beginning of the render pass before being transitioned to INPUT_ATTACHMENT state.
+ }
+ break;
+
default: UNEXPECTED("Unexpected resource type");
}
}
@@ -472,4 +481,20 @@ VkDescriptorImageInfo ShaderResourceCacheVk::Resource::GetSamplerDescriptorWrite
return DescrImgInfo;
}
+VkDescriptorImageInfo ShaderResourceCacheVk::Resource::GetInputAttachmentDescriptorWriteInfo() const
+{
+ VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::InputAttachment, "Input attachment resource is expected");
+ DEV_CHECK_ERR(pObject != nullptr, "Unable to get input attachment write info: cached object is null");
+
+ auto* pTexViewVk = pObject.RawPtr<const TextureViewVkImpl>();
+ VERIFY_EXPR(pTexViewVk->GetDesc().ViewType == TEXTURE_VIEW_SHADER_RESOURCE);
+
+ VkDescriptorImageInfo DescrImgInfo;
+ DescrImgInfo.sampler = VK_NULL_HANDLE;
+ DescrImgInfo.imageView = pTexViewVk->GetVulkanImageView();
+ DescrImgInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+
+ return DescrImgInfo;
+}
+
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
index a02cd8bb..4f28af80 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
@@ -526,6 +526,11 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice*
{
VERIFY_EXPR(SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage || SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer);
AddResource(s, Layout, Resources, SepImg);
+ },
+ [&](const SPIRVShaderResourceAttribs& InputAtt, Uint32)
+ {
+ VERIFY_EXPR(InputAtt.Type == SPIRVShaderResourceAttribs::ResourceType::InputAttachment);
+ AddResource(s, Layout, Resources, InputAtt);
}
);
// clang-format on
@@ -640,7 +645,7 @@ void ShaderResourceLayoutVk::VkResource::CacheUniformBuffer(IDeviceObject*
Uint16& DynamicBuffersCounter) const
{
VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::UniformBuffer, "Uniform buffer resource is expected");
- RefCntAutoPtr<BufferVkImpl> pBufferVk(pBuffer, IID_BufferVk);
+ RefCntAutoPtr<BufferVkImpl> pBufferVk{pBuffer, IID_BufferVk};
#ifdef DILIGENT_DEVELOPMENT
VerifyConstantBufferBinding(SpirvAttribs, GetVariableType(), ArrayInd, pBuffer, pBufferVk.RawPtr(), DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName());
#endif
@@ -681,7 +686,7 @@ void ShaderResourceLayoutVk::VkResource::CacheStorageBuffer(IDeviceObject*
"Storage buffer resource is expected");
// clang-format on
- RefCntAutoPtr<BufferViewVkImpl> pBufferViewVk(pBufferView, IID_BufferViewVk);
+ RefCntAutoPtr<BufferViewVkImpl> pBufferViewVk{pBufferView, IID_BufferViewVk};
#ifdef DILIGENT_DEVELOPMENT
{
// HLSL buffer SRVs are mapped to storge buffers in GLSL
@@ -727,7 +732,7 @@ void ShaderResourceLayoutVk::VkResource::CacheTexelBuffer(IDeviceObject*
"Uniform or storage buffer resource is expected");
// clang-format on
- RefCntAutoPtr<BufferViewVkImpl> pBufferViewVk(pBufferView, IID_BufferViewVk);
+ RefCntAutoPtr<BufferViewVkImpl> pBufferViewVk{pBufferView, IID_BufferViewVk};
#ifdef DILIGENT_DEVELOPMENT
{
// HLSL buffer SRVs are mapped to storge buffers in GLSL
@@ -776,7 +781,7 @@ void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject*
"Storage image, separate image or sampled image resource is expected");
// clang-format on
- RefCntAutoPtr<TextureViewVkImpl> pTexViewVk0(pTexView, IID_TextureViewVk);
+ RefCntAutoPtr<TextureViewVkImpl> pTexViewVk0{pTexView, IID_TextureViewVk};
#ifdef DILIGENT_DEVELOPMENT
{
// HLSL buffer SRVs are mapped to storge buffers in GLSL
@@ -840,7 +845,7 @@ void ShaderResourceLayoutVk::VkResource::CacheSeparateSampler(IDeviceObject*
VERIFY(SpirvAttribs.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);
+ RefCntAutoPtr<SamplerVkImpl> pSamplerVk{pSampler, IID_Sampler};
#ifdef DILIGENT_DEVELOPMENT
if (pSampler != nullptr && pSamplerVk == nullptr)
{
@@ -868,6 +873,28 @@ void ShaderResourceLayoutVk::VkResource::CacheSeparateSampler(IDeviceObject*
}
}
+void ShaderResourceLayoutVk::VkResource::CacheInputAttachment(IDeviceObject* pTexView,
+ ShaderResourceCacheVk::Resource& DstRes,
+ VkDescriptorSet vkDescrSet,
+ Uint32 ArrayInd) const
+{
+ VERIFY(SpirvAttribs.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());
+#endif
+ if (UpdateCachedResource(DstRes, std::move(pTexViewVk0), [](const TextureViewVkImpl*, const TextureViewVkImpl*) {}))
+ {
+ // Do not update descriptor for a dynamic image. All dynamic resource descriptors
+ // are updated at once by CommitDynamicResources() when SRB is committed.
+ if (vkDescrSet != VK_NULL_HANDLE && GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
+ {
+ VkDescriptorImageInfo DescrImgInfo = DstRes.GetInputAttachmentDescriptorWriteInfo();
+ UpdateDescriptorHandle(vkDescrSet, ArrayInd, &DescrImgInfo, nullptr, nullptr);
+ }
+ //
+ }
+}
void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint32 ArrayIndex, ShaderResourceCacheVk& ResourceCache) const
{
@@ -898,6 +925,7 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint3
if (pObj)
{
+ static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 11, "Please handle the new resource type below");
switch (SpirvAttribs.Type)
{
case SPIRVShaderResourceAttribs::ResourceType::UniformBuffer:
@@ -945,6 +973,10 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint3
}
break;
+ case SPIRVShaderResourceAttribs::ResourceType::InputAttachment:
+ CacheInputAttachment(pObj, DstRes, vkDescrSet, ArrayIndex);
+ break;
+
default: UNEXPECTED("Unknown resource type ", static_cast<Int32>(SpirvAttribs.Type));
}
}
diff --git a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
index 2a634162..ca04f900 100644
--- a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
@@ -139,6 +139,10 @@ TextureVkImpl::TextureVkImpl(IReferenceCounters* pRefCounters,
{
ImageCI.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
}
+ if (m_Desc.BindFlags & BIND_INPUT_ATTACHMENT)
+ {
+ ImageCI.usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
+ }
if (m_Desc.MiscFlags & MISC_TEXTURE_FLAG_GENERATE_MIPS)
{
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp
index d5e4f48b..25966163 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp
@@ -1140,7 +1140,6 @@ VkBorderColor BorderColorToVkBorderColor(const Float32 BorderColor[])
static VkAccessFlags ResourceStateFlagToVkAccessFlags(RESOURCE_STATE StateFlag)
{
// Currently not used:
- //VK_ACCESS_INPUT_ATTACHMENT_READ_BIT
//VK_ACCESS_HOST_READ_BIT
//VK_ACCESS_HOST_WRITE_BIT
//VK_ACCESS_MEMORY_READ_BIT
@@ -1155,7 +1154,7 @@ static VkAccessFlags ResourceStateFlagToVkAccessFlags(RESOURCE_STATE StateFlag)
//VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NVX
//VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NVX
- static_assert(RESOURCE_STATE_MAX_BIT == 0x8000, "This function must be updated to handle new resource state flag");
+ static_assert(RESOURCE_STATE_MAX_BIT == 0x10000, "This function must be updated to handle new resource state flag");
VERIFY((StateFlag & (StateFlag - 1)) == 0, "Only single bit must be set");
switch (StateFlag)
{
@@ -1175,6 +1174,7 @@ static VkAccessFlags ResourceStateFlagToVkAccessFlags(RESOURCE_STATE StateFlag)
case RESOURCE_STATE_COPY_SOURCE: return VK_ACCESS_TRANSFER_READ_BIT;
case RESOURCE_STATE_RESOLVE_DEST: return VK_ACCESS_MEMORY_READ_BIT;
case RESOURCE_STATE_RESOLVE_SOURCE: return VK_ACCESS_MEMORY_WRITE_BIT;
+ case RESOURCE_STATE_INPUT_ATTACHMENT: return VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
case RESOURCE_STATE_PRESENT: return VK_ACCESS_MEMORY_READ_BIT;
// clang-format on
@@ -1203,7 +1203,7 @@ public:
}
private:
- static constexpr const Uint32 MaxFlagBitPos = 15;
+ static constexpr const Uint32 MaxFlagBitPos = 16;
std::array<VkAccessFlags, MaxFlagBitPos + 1> FlagBitPosToVkAccessFlagsMap;
};
@@ -1235,7 +1235,7 @@ RESOURCE_STATE VkAccessFlagsToResourceStates(VkAccessFlagBits AccessFlagBit)
case VK_ACCESS_INDEX_READ_BIT: return RESOURCE_STATE_INDEX_BUFFER;
case VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT: return RESOURCE_STATE_VERTEX_BUFFER;
case VK_ACCESS_UNIFORM_READ_BIT: return RESOURCE_STATE_CONSTANT_BUFFER;
- case VK_ACCESS_INPUT_ATTACHMENT_READ_BIT: return RESOURCE_STATE_UNKNOWN;
+ case VK_ACCESS_INPUT_ATTACHMENT_READ_BIT: return RESOURCE_STATE_INPUT_ATTACHMENT;
case VK_ACCESS_SHADER_READ_BIT: return RESOURCE_STATE_SHADER_RESOURCE;
case VK_ACCESS_SHADER_WRITE_BIT: return RESOURCE_STATE_UNORDERED_ACCESS;
case VK_ACCESS_COLOR_ATTACHMENT_READ_BIT: return RESOURCE_STATE_RENDER_TARGET;
@@ -1304,7 +1304,7 @@ RESOURCE_STATE VkAccessFlagsToResourceStates(VkAccessFlags AccessFlags)
-VkImageLayout ResourceStateToVkImageLayout(RESOURCE_STATE StateFlag)
+VkImageLayout ResourceStateToVkImageLayout(RESOURCE_STATE StateFlag, bool IsInsideRenderPass)
{
if (StateFlag == RESOURCE_STATE_UNKNOWN)
{
@@ -1317,7 +1317,7 @@ VkImageLayout ResourceStateToVkImageLayout(RESOURCE_STATE StateFlag)
//VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL,
//VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL,
- static_assert(RESOURCE_STATE_MAX_BIT == 0x8000, "This function must be updated to handle new resource state flag");
+ static_assert(RESOURCE_STATE_MAX_BIT == 0x10000, "This function must be updated to handle new resource state flag");
VERIFY((StateFlag & (StateFlag - 1)) == 0, "Only single bit must be set");
switch (StateFlag)
{
@@ -1335,8 +1335,9 @@ VkImageLayout ResourceStateToVkImageLayout(RESOURCE_STATE StateFlag)
case RESOURCE_STATE_INDIRECT_ARGUMENT: UNEXPECTED("Invalid resource state"); return VK_IMAGE_LAYOUT_UNDEFINED;
case RESOURCE_STATE_COPY_DEST: return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
case RESOURCE_STATE_COPY_SOURCE: return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
- case RESOURCE_STATE_RESOLVE_DEST: return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ case RESOURCE_STATE_RESOLVE_DEST: return IsInsideRenderPass ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
case RESOURCE_STATE_RESOLVE_SOURCE: return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+ case RESOURCE_STATE_INPUT_ATTACHMENT: return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
case RESOURCE_STATE_PRESENT: return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
// clang-format on
@@ -1348,7 +1349,7 @@ VkImageLayout ResourceStateToVkImageLayout(RESOURCE_STATE StateFlag)
RESOURCE_STATE VkImageLayoutToResourceState(VkImageLayout Layout)
{
- static_assert(RESOURCE_STATE_MAX_BIT == 0x8000, "This function must be updated to handle new resource state flag");
+ static_assert(RESOURCE_STATE_MAX_BIT == 0x10000, "This function must be updated to handle new resource state flag");
switch (Layout)
{
// clang-format off
@@ -1421,4 +1422,93 @@ VkSurfaceTransformFlagBitsKHR SurfaceTransformToVkSurfaceTransformFlag(SURFACE_T
// clang-format on
}
+
+#define ASSERT_SAME(Val1, Val2) static_assert(static_cast<int>(Val1) == static_cast<int>(Val2), #Val1 " is expected to be equal to " #Val2)
+
+ASSERT_SAME(ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_LOAD);
+ASSERT_SAME(ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_LOAD_OP_CLEAR);
+ASSERT_SAME(ATTACHMENT_LOAD_OP_DISCARD, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
+VkAttachmentLoadOp AttachmentLoadOpToVkAttachmentLoadOp(ATTACHMENT_LOAD_OP LoadOp)
+{
+ return static_cast<VkAttachmentLoadOp>(LoadOp);
+}
+ATTACHMENT_LOAD_OP VkAttachmentLoadOpToAttachmentLoadOp(VkAttachmentLoadOp VkLoadOp)
+{
+ return static_cast<ATTACHMENT_LOAD_OP>(VkLoadOp);
+}
+
+
+ASSERT_SAME(ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_STORE_OP_STORE);
+ASSERT_SAME(ATTACHMENT_STORE_OP_DISCARD, VK_ATTACHMENT_STORE_OP_DONT_CARE);
+VkAttachmentStoreOp AttachmentStoreOpToVkAttachmentStoreOp(ATTACHMENT_STORE_OP StoreOp)
+{
+ return static_cast<VkAttachmentStoreOp>(StoreOp);
+}
+ATTACHMENT_STORE_OP VkAttachmentStoreOpToAttachmentStoreOp(VkAttachmentStoreOp VkStoreOp)
+{
+ return static_cast<ATTACHMENT_STORE_OP>(VkStoreOp);
+}
+
+
+// clang-format off
+ASSERT_SAME(PIPELINE_STAGE_FLAG_TOP_OF_PIPE, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
+ASSERT_SAME(PIPELINE_STAGE_FLAG_DRAW_INDIRECT, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT);
+ASSERT_SAME(PIPELINE_STAGE_FLAG_VERTEX_INPUT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT);
+ASSERT_SAME(PIPELINE_STAGE_FLAG_VERTEX_SHADER, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT);
+ASSERT_SAME(PIPELINE_STAGE_FLAG_HULL_SHADER, VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT);
+ASSERT_SAME(PIPELINE_STAGE_FLAG_DOMAIN_SHADER, VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT);
+ASSERT_SAME(PIPELINE_STAGE_FLAG_GEOMETRY_SHADER, VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT);
+ASSERT_SAME(PIPELINE_STAGE_FLAG_PIXEL_SHADER, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
+ASSERT_SAME(PIPELINE_STAGE_FLAG_EARLY_FRAGMENT_TESTS, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
+ASSERT_SAME(PIPELINE_STAGE_FLAG_LATE_FRAGMENT_TESTS, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
+ASSERT_SAME(PIPELINE_STAGE_FLAG_RENDER_TARGET, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
+ASSERT_SAME(PIPELINE_STAGE_FLAG_COMPUTE_SHADER, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
+ASSERT_SAME(PIPELINE_STAGE_FLAG_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT);
+ASSERT_SAME(PIPELINE_STAGE_FLAG_BOTTOM_OF_PIPE, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
+ASSERT_SAME(PIPELINE_STAGE_FLAG_HOST, VK_PIPELINE_STAGE_HOST_BIT);
+ASSERT_SAME(PIPELINE_STAGE_FLAG_CONDITIONAL_RENDERING, VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT);
+ASSERT_SAME(PIPELINE_STAGE_FLAG_SHADING_RATE_TEXTURE, VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV);
+ASSERT_SAME(PIPELINE_STAGE_FLAG_RAY_TRACING_SHADER, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_NV);
+ASSERT_SAME(PIPELINE_STAGE_FLAG_ACCELERATION_STRUCTURE_BUILD, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV);
+ASSERT_SAME(PIPELINE_STAGE_FLAG_TASK_SHADER, VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV);
+ASSERT_SAME(PIPELINE_STAGE_FLAG_MESH_SHADER, VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV);
+ASSERT_SAME(PIPELINE_STAGE_FLAG_FRAGMENT_DENSITY_PROCESS, VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT);
+// clang-format on
+VkPipelineStageFlags PipelineStageFlagsToVkPipelineStageFlags(PIPELINE_STAGE_FLAGS PipelineStageFlags)
+{
+ return static_cast<VkPipelineStageFlags>(PipelineStageFlags);
+}
+
+
+// clang-format off
+static_assert(ACCESS_FLAG_NONE == 0, "");
+ASSERT_SAME(ACCESS_FLAG_INDIRECT_COMMAND_READ, VK_ACCESS_INDIRECT_COMMAND_READ_BIT);
+ASSERT_SAME(ACCESS_FLAG_INDEX_READ, VK_ACCESS_INDEX_READ_BIT);
+ASSERT_SAME(ACCESS_FLAG_VERTEX_READ, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT);
+ASSERT_SAME(ACCESS_FLAG_UNIFORM_READ, VK_ACCESS_UNIFORM_READ_BIT);
+ASSERT_SAME(ACCESS_FLAG_INPUT_ATTACHMENT_READ, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT);
+ASSERT_SAME(ACCESS_FLAG_SHADER_READ, VK_ACCESS_SHADER_READ_BIT);
+ASSERT_SAME(ACCESS_FLAG_SHADER_WRITE, VK_ACCESS_SHADER_WRITE_BIT);
+ASSERT_SAME(ACCESS_FLAG_RENDER_TARGET_READ, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT);
+ASSERT_SAME(ACCESS_FLAG_RENDER_TARGET_WRITE, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
+ASSERT_SAME(ACCESS_FLAG_DEPTH_STENCIL_READ, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT);
+ASSERT_SAME(ACCESS_FLAG_DEPTH_STENCIL_WRITE, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT);
+ASSERT_SAME(ACCESS_FLAG_COPY_SRC, VK_ACCESS_TRANSFER_READ_BIT);
+ASSERT_SAME(ACCESS_FLAG_COPY_DST, VK_ACCESS_TRANSFER_WRITE_BIT);
+ASSERT_SAME(ACCESS_FLAG_HOST_READ, VK_ACCESS_HOST_READ_BIT);
+ASSERT_SAME(ACCESS_FLAG_HOST_WRITE, VK_ACCESS_HOST_WRITE_BIT);
+ASSERT_SAME(ACCESS_FLAG_MEMORY_READ, VK_ACCESS_MEMORY_READ_BIT);
+ASSERT_SAME(ACCESS_FLAG_MEMORY_WRITE, VK_ACCESS_MEMORY_WRITE_BIT);
+ASSERT_SAME(ACCESS_FLAG_CONDITIONAL_RENDERING_READ, VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT);
+ASSERT_SAME(ACCESS_FLAG_SHADING_RATE_TEXTURE_READ, VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV);
+ASSERT_SAME(ACCESS_FLAG_ACCELERATION_STRUCTURE_READ, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV);
+ASSERT_SAME(ACCESS_FLAG_ACCELERATION_STRUCTURE_WRITE, VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV);
+ASSERT_SAME(ACCESS_FLAG_FRAGMENT_DENSITY_MAP_READ, VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT);
+// clang-format on
+VkAccessFlags AccessFlagsToVkAccessFlags(ACCESS_FLAGS AccessFlags)
+{
+ return static_cast<VkAccessFlags>(AccessFlags);
+}
+#undef ASSERT_SAME
+
} // namespace Diligent