summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorassiduous <assiduous@diligentgraphics.com>2020-08-04 21:05:42 +0000
committerassiduous <assiduous@diligentgraphics.com>2020-08-04 21:05:42 +0000
commit86bd2d7175d3e2d0f5c1c313a802a22c9f95b4ea (patch)
treee4d8d6f4f90a4805d6d230d6fd7f49390be4cdab
parentAdded render pass MS resolve test (diff)
downloadDiligentCore-86bd2d7175d3e2d0f5c1c313a802a22c9f95b4ea.tar.gz
DiligentCore-86bd2d7175d3e2d0f5c1c313a802a22c9f95b4ea.zip
Implemented input attachments in Vulkan backend; added test
-rw-r--r--Graphics/GLSLTools/include/SPIRVShaderResources.hpp22
-rw-r--r--Graphics/GLSLTools/src/SPIRVShaderResources.cpp40
-rw-r--r--Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp2
-rw-r--r--Graphics/GraphicsEngine/include/TextureBase.hpp3
-rw-r--r--Graphics/GraphicsEngine/interface/GraphicsTypes.h15
-rw-r--r--Graphics/GraphicsEngine/interface/Shader.h11
-rw-r--r--Graphics/GraphicsEngine/src/RenderPassBase.cpp8
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp1
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp5
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp3
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp25
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp42
-rw-r--r--Tests/DiligentCoreAPITest/include/InlineShaders/DrawCommandTestGLSL.h17
-rw-r--r--Tests/DiligentCoreAPITest/src/RenderPassTest.cpp238
-rw-r--r--Tests/DiligentCoreAPITest/src/TestingEnvironment.cpp4
-rw-r--r--Tests/DiligentCoreAPITest/src/Vulkan/DrawCommandReferenceVk.cpp269
16 files changed, 667 insertions, 38 deletions
diff --git a/Graphics/GLSLTools/include/SPIRVShaderResources.hpp b/Graphics/GLSLTools/include/SPIRVShaderResources.hpp
index 96e778a0..7a1b93ce 100644
--- a/Graphics/GLSLTools/include/SPIRVShaderResources.hpp
+++ b/Graphics/GLSLTools/include/SPIRVShaderResources.hpp
@@ -70,6 +70,7 @@ struct SPIRVShaderResourceAttribs
AtomicCounter,
SeparateImage,
SeparateSampler,
+ InputAttachment,
NumResourceTypes
};
@@ -205,7 +206,8 @@ public:
Uint32 GetNumSmpldImgs()const noexcept{ return (m_AtomicCounterOffset - m_SampledImageOffset); }
Uint32 GetNumACs ()const noexcept{ return (m_SeparateSamplerOffset - m_AtomicCounterOffset); }
Uint32 GetNumSepSmplrs()const noexcept{ return (m_SeparateImageOffset - m_SeparateSamplerOffset);}
- Uint32 GetNumSepImgs ()const noexcept{ return (m_TotalResources - m_SeparateImageOffset); }
+ Uint32 GetNumSepImgs ()const noexcept{ return (m_InputAttachmentOffset - m_SeparateImageOffset); }
+ Uint32 GetNumInptAtts ()const noexcept{ return (m_TotalResources - m_InputAttachmentOffset);}
Uint32 GetTotalResources() const noexcept { return m_TotalResources; }
Uint32 GetNumShaderStageInputs()const noexcept { return m_NumShaderStageInputs; }
@@ -216,6 +218,7 @@ public:
const SPIRVShaderResourceAttribs& GetAC (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumACs(), m_AtomicCounterOffset ); }
const SPIRVShaderResourceAttribs& GetSepSmplr(Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSepSmplrs(), m_SeparateSamplerOffset); }
const SPIRVShaderResourceAttribs& GetSepImg (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSepImgs(), m_SeparateImageOffset ); }
+ const SPIRVShaderResourceAttribs& GetInptAtt (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumInptAtts(), m_InputAttachmentOffset); }
const SPIRVShaderResourceAttribs& GetResource(Uint32 n)const noexcept{ return GetResAttribs(n, GetTotalResources(), 0 ); }
// clang-format on
@@ -243,6 +246,7 @@ public:
Uint32 NumACs = 0;
Uint32 NumSepSmplrs = 0;
Uint32 NumSepImgs = 0;
+ Uint32 NumInptAtts = 0;
};
SHADER_TYPE GetShaderType() const noexcept { return m_ShaderType; }
@@ -254,14 +258,16 @@ public:
typename THandleSmplImg,
typename THandleAC,
typename THandleSepSmpl,
- typename THandleSepImg>
+ typename THandleSepImg,
+ typename THandleInptAtt>
void ProcessResources(THandleUB HandleUB,
THandleSB HandleSB,
THandleImg HandleImg,
THandleSmplImg HandleSmplImg,
THandleAC HandleAC,
THandleSepSmpl HandleSepSmpl,
- THandleSepImg HandleSepImg) const
+ THandleSepImg HandleSepImg,
+ THandleInptAtt HandleInptAtt) const
{
for (Uint32 n = 0; n < GetNumUBs(); ++n)
{
@@ -304,6 +310,14 @@ public:
const auto& SepImg = GetSepImg(n);
HandleSepImg(SepImg, n);
}
+
+ for (Uint32 n = 0; n < GetNumInptAtts(); ++n)
+ {
+ const auto& InptAtt = GetInptAtt(n);
+ HandleInptAtt(InptAtt, n);
+ }
+
+ static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 11, "Please handle the new resource type here, if needed");
}
template <typename THandler>
@@ -359,6 +373,7 @@ private:
SPIRVShaderResourceAttribs& GetAC (Uint32 n)noexcept{ return GetResAttribs(n, GetNumACs(), m_AtomicCounterOffset ); }
SPIRVShaderResourceAttribs& GetSepSmplr(Uint32 n)noexcept{ return GetResAttribs(n, GetNumSepSmplrs(), m_SeparateSamplerOffset); }
SPIRVShaderResourceAttribs& GetSepImg (Uint32 n)noexcept{ return GetResAttribs(n, GetNumSepImgs(), m_SeparateImageOffset ); }
+ SPIRVShaderResourceAttribs& GetInptAtt (Uint32 n)noexcept{ return GetResAttribs(n, GetNumInptAtts(), m_InputAttachmentOffset); }
SPIRVShaderResourceAttribs& GetResource(Uint32 n)noexcept{ return GetResAttribs(n, GetTotalResources(), 0 ); }
// clang-format on
@@ -384,6 +399,7 @@ private:
OffsetType m_AtomicCounterOffset = 0;
OffsetType m_SeparateSamplerOffset = 0;
OffsetType m_SeparateImageOffset = 0;
+ OffsetType m_InputAttachmentOffset = 0;
OffsetType m_TotalResources = 0;
OffsetType m_NumShaderStageInputs = 0;
diff --git a/Graphics/GLSLTools/src/SPIRVShaderResources.cpp b/Graphics/GLSLTools/src/SPIRVShaderResources.cpp
index 46705ace..0dd3e4ae 100644
--- a/Graphics/GLSLTools/src/SPIRVShaderResources.cpp
+++ b/Graphics/GLSLTools/src/SPIRVShaderResources.cpp
@@ -91,7 +91,7 @@ ShaderResourceDesc SPIRVShaderResourceAttribs::GetResourceDesc() const
ResourceDesc.Name = Name;
ResourceDesc.ArraySize = ArraySize;
- static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 10, "Please update switch statement below");
+ static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 11, "Please handle the new resource type below");
switch (Type)
{
case SPIRVShaderResourceAttribs::ResourceType::UniformBuffer:
@@ -137,6 +137,10 @@ ShaderResourceDesc SPIRVShaderResourceAttribs::GetResourceDesc() const
ResourceDesc.Type = SHADER_RESOURCE_TYPE_SAMPLER;
break;
+ case SPIRVShaderResourceAttribs::ResourceType::InputAttachment:
+ ResourceDesc.Type = SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT;
+ break;
+
default:
UNEXPECTED("Unknown SPIRV resource type");
}
@@ -245,6 +249,7 @@ SPIRVShaderResources::SPIRVShaderResources(IMemoryAllocator& Allocator,
size_t ResourceNamesPoolSize = 0;
for (const auto& ub : resources.uniform_buffers)
ResourceNamesPoolSize += GetUBName(Compiler, ub, ParsedIRSource).length() + 1;
+ static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 11, "Please account for the new resource type below");
for (auto* pResType :
{
&resources.storage_buffers,
@@ -252,10 +257,11 @@ SPIRVShaderResources::SPIRVShaderResources(IMemoryAllocator& Allocator,
&resources.sampled_images,
&resources.atomic_counters,
&resources.separate_images,
- &resources.separate_samplers
- //clang-format off
+ &resources.separate_samplers,
+ &resources.subpass_inputs
+ // clang-format off
})
- //clang-format on
+ // clang-format on
{
for (const auto& res : *pResType)
ResourceNamesPoolSize += res.name.length() + 1;
@@ -322,6 +328,8 @@ SPIRVShaderResources::SPIRVShaderResources(IMemoryAllocator& Allocator,
ResCounters.NumACs = static_cast<Uint32>(resources.atomic_counters.size());
ResCounters.NumSepSmplrs = static_cast<Uint32>(resources.separate_samplers.size());
ResCounters.NumSepImgs = static_cast<Uint32>(resources.separate_images.size());
+ ResCounters.NumInptAtts = static_cast<Uint32>(resources.subpass_inputs.size());
+ static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 11, "Please set the new resource type counter here");
Initialize(Allocator, ResCounters, NumShaderStageInputs, ResourceNamesPoolSize);
{
@@ -469,6 +477,21 @@ SPIRVShaderResources::SPIRVShaderResources(IMemoryAllocator& Allocator,
VERIFY_EXPR(CurrSepImg == GetNumSepImgs());
}
+ {
+ Uint32 CurrSubpassInput = 0;
+ for (const auto& SubpassInput : resources.subpass_inputs)
+ {
+ new (&GetInptAtt(CurrSubpassInput++))
+ SPIRVShaderResourceAttribs(Compiler,
+ SubpassInput,
+ m_ResourceNames.CopyString(SubpassInput.name),
+ SPIRVShaderResourceAttribs::ResourceType::InputAttachment);
+ }
+ VERIFY_EXPR(CurrSubpassInput == GetNumInptAtts());
+ }
+
+ static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 11, "Please initialize SPIRVShaderResourceAttribs for the new resource type here");
+
if (CombinedSamplerSuffix != nullptr)
{
m_CombinedSamplerSuffix = m_ResourceNames.CopyString(CombinedSamplerSuffix);
@@ -531,7 +554,9 @@ void SPIRVShaderResources::Initialize(IMemoryAllocator& Allocator,
m_AtomicCounterOffset = AdvanceOffset(Counters.NumACs);
m_SeparateSamplerOffset = AdvanceOffset(Counters.NumSepSmplrs);
m_SeparateImageOffset = AdvanceOffset(Counters.NumSepImgs);
+ m_InputAttachmentOffset = AdvanceOffset(Counters.NumInptAtts);
m_TotalResources = AdvanceOffset(0);
+ static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 11, "Please update the new resource type offset");
VERIFY(NumShaderStageInputs <= MaxOffset, "Max offset exceeded");
m_NumShaderStageInputs = static_cast<OffsetType>(NumShaderStageInputs);
@@ -692,6 +717,13 @@ std::string SPIRVShaderResources::DumpResources()
ss << std::endl
<< std::setw(3) << ResNum << " Separate Img ";
DumpResource(SepImg);
+ },
+ [&](const SPIRVShaderResourceAttribs& InptAtt, Uint32) //
+ {
+ VERIFY(InptAtt.Type == SPIRVShaderResourceAttribs::ResourceType::InputAttachment, "Unexpected resource type");
+ ss << std::endl
+ << std::setw(3) << ResNum << " Input Attachment ";
+ DumpResource(InptAtt);
} //
);
VERIFY_EXPR(ResNum == GetTotalResources());
diff --git a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp
index 0a4afd54..5cefca34 100644
--- a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp
+++ b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp
@@ -1019,6 +1019,7 @@ String GetBufferDescString(const BufferDesc& Desc)
const Char* GetResourceStateFlagString(RESOURCE_STATE State)
{
VERIFY((State & (State - 1)) == 0, "Single state is expected");
+ static_assert(RESOURCE_STATE_MAX_BIT == 0x10000, "Please update this function to handle the new resource state");
switch (State)
{
// clang-format off
@@ -1038,6 +1039,7 @@ const Char* GetResourceStateFlagString(RESOURCE_STATE State)
case RESOURCE_STATE_COPY_SOURCE: return "COPY_SOURCE";
case RESOURCE_STATE_RESOLVE_DEST: return "RESOLVE_DEST";
case RESOURCE_STATE_RESOLVE_SOURCE: return "RESOLVE_SOURCE";
+ case RESOURCE_STATE_INPUT_ATTACHMENT: return "INPUT_ATTACHMENT";
case RESOURCE_STATE_PRESENT: return "PRESENT";
// clang-format on
default:
diff --git a/Graphics/GraphicsEngine/include/TextureBase.hpp b/Graphics/GraphicsEngine/include/TextureBase.hpp
index 38414be2..fd0256b6 100644
--- a/Graphics/GraphicsEngine/include/TextureBase.hpp
+++ b/Graphics/GraphicsEngine/include/TextureBase.hpp
@@ -123,6 +123,9 @@ public:
") correspond to one of ", pDevice->GetCommandQueueCount(), " available device command queues");
this->m_Desc.CommandQueueMask &= DeviceQueuesMask;
+ if ((this->m_Desc.BindFlags & BIND_INPUT_ATTACHMENT) != 0)
+ this->m_Desc.BindFlags |= BIND_SHADER_RESOURCE;
+
// Validate correctness of texture description
ValidateTextureDesc(this->m_Desc);
}
diff --git a/Graphics/GraphicsEngine/interface/GraphicsTypes.h b/Graphics/GraphicsEngine/interface/GraphicsTypes.h
index 3c0ca99a..727888d9 100644
--- a/Graphics/GraphicsEngine/interface/GraphicsTypes.h
+++ b/Graphics/GraphicsEngine/interface/GraphicsTypes.h
@@ -1644,6 +1644,7 @@ struct VulkanDescriptorPoolSize
Uint32 NumStorageBufferDescriptors DEFAULT_INITIALIZER(0);
Uint32 NumUniformTexelBufferDescriptors DEFAULT_INITIALIZER(0);
Uint32 NumStorageTexelBufferDescriptors DEFAULT_INITIALIZER(0);
+ Uint32 NumInputAttachmentDescriptors DEFAULT_INITIALIZER(0);
#if DILIGENT_CPP_INTERFACE
VulkanDescriptorPoolSize()noexcept {}
@@ -1656,7 +1657,8 @@ struct VulkanDescriptorPoolSize
Uint32 _NumUniformBufferDescriptors,
Uint32 _NumStorageBufferDescriptors,
Uint32 _NumUniformTexelBufferDescriptors,
- Uint32 _NumStorageTexelBufferDescriptors)noexcept :
+ Uint32 _NumStorageTexelBufferDescriptors,
+ Uint32 _NumInputAttachmentDescriptors)noexcept :
MaxDescriptorSets {_MaxDescriptorSets },
NumSeparateSamplerDescriptors {_NumSeparateSamplerDescriptors },
NumCombinedSamplerDescriptors {_NumCombinedSamplerDescriptors },
@@ -1665,7 +1667,8 @@ struct VulkanDescriptorPoolSize
NumUniformBufferDescriptors {_NumUniformBufferDescriptors },
NumStorageBufferDescriptors {_NumStorageBufferDescriptors },
NumUniformTexelBufferDescriptors{_NumUniformTexelBufferDescriptors},
- NumStorageTexelBufferDescriptors{_NumStorageTexelBufferDescriptors}
+ NumStorageTexelBufferDescriptors{_NumStorageTexelBufferDescriptors},
+ NumInputAttachmentDescriptors {_NumInputAttachmentDescriptors }
{
// On clang aggregate initialization fails to compile if
// structure members have default initializers
@@ -1700,8 +1703,8 @@ struct EngineVkCreateInfo DILIGENT_DERIVE(EngineCreateInfo)
/// the engine creates another one.
VulkanDescriptorPoolSize MainDescriptorPoolSize
#if DILIGENT_CPP_INTERFACE
- //Max SepSm CmbSm SmpImg StrImg UB SB UTxB StTxB
- {8192, 1024, 8192, 8192, 1024, 4096, 4096, 1024, 1024}
+ //Max SepSm CmbSm SmpImg StrImg UB SB UTxB StTxB InptAtt
+ {8192, 1024, 8192, 8192, 1024, 4096, 4096, 1024, 1024, 256}
#endif
;
@@ -1712,8 +1715,8 @@ struct EngineVkCreateInfo DILIGENT_DERIVE(EngineCreateInfo)
VulkanDescriptorPoolSize DynamicDescriptorPoolSize
#if DILIGENT_CPP_INTERFACE
- //Max SepSm CmbSm SmpImg StrImg UB SB UTxB StTxB
- {2048, 256, 2048, 2048, 256, 1024, 1024, 256, 256}
+ //Max SepSm CmbSm SmpImg StrImg UB SB UTxB StTxB InptAtt
+ {2048, 256, 2048, 2048, 256, 1024, 1024, 256, 256, 64}
#endif
;
diff --git a/Graphics/GraphicsEngine/interface/Shader.h b/Graphics/GraphicsEngine/interface/Shader.h
index eacd35f0..f3df92d3 100644
--- a/Graphics/GraphicsEngine/interface/Shader.h
+++ b/Graphics/GraphicsEngine/interface/Shader.h
@@ -283,8 +283,10 @@ struct ShaderCreateInfo
};
typedef struct ShaderCreateInfo ShaderCreateInfo;
+// clang-format off
/// Describes shader resource type
-DILIGENT_TYPED_ENUM(SHADER_RESOURCE_TYPE, Uint8){
+DILIGENT_TYPED_ENUM(SHADER_RESOURCE_TYPE, Uint8)
+{
/// Shader resource type is unknown
SHADER_RESOURCE_TYPE_UNKNOWN = 0,
@@ -304,7 +306,12 @@ DILIGENT_TYPED_ENUM(SHADER_RESOURCE_TYPE, Uint8){
SHADER_RESOURCE_TYPE_BUFFER_UAV,
/// Sampler (separate sampler)
- SHADER_RESOURCE_TYPE_SAMPLER};
+ SHADER_RESOURCE_TYPE_SAMPLER,
+
+ /// Input attachment in a render pass
+ SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT
+};
+// clang-format on
/// Shader resource description
struct ShaderResourceDesc
diff --git a/Graphics/GraphicsEngine/src/RenderPassBase.cpp b/Graphics/GraphicsEngine/src/RenderPassBase.cpp
index a0548e4d..b6b38dd0 100644
--- a/Graphics/GraphicsEngine/src/RenderPassBase.cpp
+++ b/Graphics/GraphicsEngine/src/RenderPassBase.cpp
@@ -89,7 +89,8 @@ void ValidateRenderPassDesc(const RenderPassDesc& Desc)
Attachment.InitialState != RESOURCE_STATE_RESOLVE_DEST &&
Attachment.InitialState != RESOURCE_STATE_RESOLVE_SOURCE &&
Attachment.InitialState != RESOURCE_STATE_COPY_DEST &&
- Attachment.InitialState != RESOURCE_STATE_COPY_SOURCE)
+ Attachment.InitialState != RESOURCE_STATE_COPY_SOURCE &&
+ Attachment.InitialState != RESOURCE_STATE_INPUT_ATTACHMENT)
{
LOG_RENDER_PASS_ERROR_AND_THROW("the initial state of depth-stencil attachment ", i, " (", GetResourceStateString(Attachment.InitialState), ") is invalid.");
}
@@ -101,7 +102,8 @@ void ValidateRenderPassDesc(const RenderPassDesc& Desc)
Attachment.FinalState != RESOURCE_STATE_RESOLVE_DEST &&
Attachment.FinalState != RESOURCE_STATE_RESOLVE_SOURCE &&
Attachment.FinalState != RESOURCE_STATE_COPY_DEST &&
- Attachment.FinalState != RESOURCE_STATE_COPY_SOURCE)
+ Attachment.FinalState != RESOURCE_STATE_COPY_SOURCE &&
+ Attachment.FinalState != RESOURCE_STATE_INPUT_ATTACHMENT)
{
LOG_RENDER_PASS_ERROR_AND_THROW("the final state of depth-stencil attachment ", i, " (", GetResourceStateString(Attachment.FinalState), ") is invalid.");
}
@@ -114,6 +116,7 @@ void ValidateRenderPassDesc(const RenderPassDesc& Desc)
Attachment.InitialState != RESOURCE_STATE_RESOLVE_DEST &&
Attachment.InitialState != RESOURCE_STATE_RESOLVE_SOURCE &&
Attachment.InitialState != RESOURCE_STATE_COPY_SOURCE &&
+ Attachment.InitialState != RESOURCE_STATE_INPUT_ATTACHMENT &&
Attachment.InitialState != RESOURCE_STATE_PRESENT)
{
LOG_RENDER_PASS_ERROR_AND_THROW("the initial state of color attachment ", i, " (", GetResourceStateString(Attachment.InitialState), ") is invalid.");
@@ -125,6 +128,7 @@ void ValidateRenderPassDesc(const RenderPassDesc& Desc)
Attachment.FinalState != RESOURCE_STATE_RESOLVE_DEST &&
Attachment.FinalState != RESOURCE_STATE_RESOLVE_SOURCE &&
Attachment.FinalState != RESOURCE_STATE_COPY_SOURCE &&
+ Attachment.FinalState != RESOURCE_STATE_INPUT_ATTACHMENT &&
Attachment.FinalState != RESOURCE_STATE_PRESENT)
{
LOG_RENDER_PASS_ERROR_AND_THROW("the final state of color attachment ", i, " (", GetResourceStateString(Attachment.FinalState), ") is invalid.");
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/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/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/Tests/DiligentCoreAPITest/include/InlineShaders/DrawCommandTestGLSL.h b/Tests/DiligentCoreAPITest/include/InlineShaders/DrawCommandTestGLSL.h
index 83e63258..4c74e32c 100644
--- a/Tests/DiligentCoreAPITest/include/InlineShaders/DrawCommandTestGLSL.h
+++ b/Tests/DiligentCoreAPITest/include/InlineShaders/DrawCommandTestGLSL.h
@@ -93,6 +93,23 @@ void main()
)"
};
+const std::string InputAttachmentTest_FS{
+R"(
+#version 420 core
+
+layout(input_attachment_index = 0, binding = 0) uniform subpassInput in_Color;
+layout(location = 0) in vec3 in_VSOutColor;
+layout(location = 0) out vec4 out_Color;
+
+void main()
+{
+ out_Color.rgb = in_VSOutColor.rgb * 0.125;
+ out_Color.rgb += (vec3(1.0, 1.0, 1.0) - subpassLoad(in_Color).brg) * 0.875;
+ out_Color.a = 1.0;
+}
+)"
+};
+
// clang-format on
} // namespace GLSL
diff --git a/Tests/DiligentCoreAPITest/src/RenderPassTest.cpp b/Tests/DiligentCoreAPITest/src/RenderPassTest.cpp
index 0f0e9567..3f0dc23c 100644
--- a/Tests/DiligentCoreAPITest/src/RenderPassTest.cpp
+++ b/Tests/DiligentCoreAPITest/src/RenderPassTest.cpp
@@ -32,6 +32,8 @@
#include "gtest/gtest.h"
+#include "InlineShaders/DrawCommandTestGLSL.h"
+
namespace Diligent
{
@@ -634,8 +636,242 @@ TEST_F(RenderPassTest, MSResolve)
Present();
}
-TEST_F(RenderPassTest, InputAttachments)
+TEST_F(RenderPassTest, InputAttachment)
{
+ auto* pEnv = TestingEnvironment::GetInstance();
+ auto* pDevice = pEnv->GetDevice();
+ auto* pSwapChain = pEnv->GetSwapChain();
+ auto* pContext = pEnv->GetDeviceContext();
+
+ constexpr float ClearColor[] = {0.5f, 0.125f, 0.25f, 0.25f};
+
+ RefCntAutoPtr<ITestingSwapChain> pTestingSwapChain(pSwapChain, IID_TestingSwapChain);
+ if (pTestingSwapChain)
+ {
+ pContext->Flush();
+ pContext->InvalidateState();
+
+ auto deviceType = pDevice->GetDeviceCaps().DevType;
+ switch (deviceType)
+ {
+#if D3D11_SUPPORTED
+ case RENDER_DEVICE_TYPE_D3D11:
+ RenderDrawCommandReferenceD3D11(pSwapChain);
+ break;
+#endif
+
+#if D3D12_SUPPORTED
+ case RENDER_DEVICE_TYPE_D3D12:
+ RenderDrawCommandReferenceD3D12(pSwapChain);
+ break;
+#endif
+
+#if GL_SUPPORTED || GLES_SUPPORTED
+ case RENDER_DEVICE_TYPE_GL:
+ case RENDER_DEVICE_TYPE_GLES:
+ RenderDrawCommandReferenceGL(pSwapChain);
+ break;
+
+#endif
+
+#if VULKAN_SUPPORTED
+ case RENDER_DEVICE_TYPE_VULKAN:
+ RenderPassInputAttachmentReferenceVk(pSwapChain, ClearColor);
+ break;
+#endif
+
+ default:
+ LOG_ERROR_AND_THROW("Unsupported device type");
+ }
+
+ pTestingSwapChain->TakeSnapshot();
+ }
+ TestingEnvironment::ScopedReleaseResources EnvironmentAutoReset;
+
+ const auto& SCDesc = pSwapChain->GetDesc();
+
+ RenderPassAttachmentDesc Attachments[2];
+ Attachments[0].Format = SCDesc.ColorBufferFormat;
+ Attachments[0].SampleCount = 1;
+ Attachments[0].InitialState = RESOURCE_STATE_RENDER_TARGET;
+ Attachments[0].FinalState = RESOURCE_STATE_INPUT_ATTACHMENT;
+ Attachments[0].LoadOp = ATTACHMENT_LOAD_OP_CLEAR;
+ Attachments[0].StoreOp = ATTACHMENT_STORE_OP_DISCARD;
+
+ Attachments[1].Format = SCDesc.ColorBufferFormat;
+ Attachments[1].SampleCount = 1;
+ Attachments[1].InitialState = RESOURCE_STATE_RENDER_TARGET;
+ Attachments[1].FinalState = RESOURCE_STATE_RENDER_TARGET;
+ Attachments[1].LoadOp = ATTACHMENT_LOAD_OP_CLEAR;
+ Attachments[1].StoreOp = ATTACHMENT_STORE_OP_STORE;
+
+ RefCntAutoPtr<ITexture> pTex;
+ {
+ TextureDesc TexDesc;
+ TexDesc.Type = RESOURCE_DIM_TEX_2D;
+ TexDesc.Format = SCDesc.ColorBufferFormat;
+ TexDesc.Width = SCDesc.Width;
+ TexDesc.Height = SCDesc.Height;
+ TexDesc.BindFlags = BIND_RENDER_TARGET | BIND_INPUT_ATTACHMENT;
+ TexDesc.MipLevels = 1;
+ TexDesc.Usage = USAGE_DEFAULT;
+
+ pDevice->CreateTexture(TexDesc, nullptr, &pTex);
+ ASSERT_NE(pTex, nullptr);
+ }
+
+ SubpassDesc Subpasses[2];
+
+ // clang-format off
+ AttachmentReference RTAttachmentRefs0[] =
+ {
+ {0, RESOURCE_STATE_RENDER_TARGET}
+ };
+ AttachmentReference RTAttachmentRefs1[] =
+ {
+ {1, RESOURCE_STATE_RENDER_TARGET}
+ };
+ AttachmentReference InputAttachmentRefs1[] =
+ {
+ {0, RESOURCE_STATE_INPUT_ATTACHMENT}
+ };
+ // clang-format on
+ Subpasses[0].RenderTargetAttachmentCount = _countof(RTAttachmentRefs0);
+ Subpasses[0].pRenderTargetAttachments = RTAttachmentRefs0;
+
+ Subpasses[1].RenderTargetAttachmentCount = _countof(RTAttachmentRefs1);
+ Subpasses[1].pRenderTargetAttachments = RTAttachmentRefs1;
+ Subpasses[1].InputAttachmentCount = _countof(InputAttachmentRefs1);
+ Subpasses[1].pInputAttachments = InputAttachmentRefs1;
+
+ SubpassDependencyDesc Dependencies[1];
+ Dependencies[0].SrcSubpass = 0;
+ Dependencies[0].DstSubpass = 1;
+ Dependencies[0].SrcStageMask = PIPELINE_STAGE_FLAG_RENDER_TARGET;
+ Dependencies[0].DstStageMask = PIPELINE_STAGE_FLAG_PIXEL_SHADER;
+ Dependencies[0].SrcAccessMask = ACCESS_FLAG_RENDER_TARGET_WRITE;
+ Dependencies[0].DstAccessMask = ACCESS_FLAG_SHADER_READ;
+
+ RenderPassDesc RPDesc;
+ RPDesc.Name = "Render pass input attachment test";
+ RPDesc.AttachmentCount = _countof(Attachments);
+ RPDesc.pAttachments = Attachments;
+ RPDesc.SubpassCount = _countof(Subpasses);
+ RPDesc.pSubpasses = Subpasses;
+ RPDesc.DependencyCount = _countof(Dependencies);
+ RPDesc.pDependencies = Dependencies;
+
+ RefCntAutoPtr<IRenderPass> pRenderPass;
+ pDevice->CreateRenderPass(RPDesc, &pRenderPass);
+ ASSERT_NE(pRenderPass, nullptr);
+
+ RefCntAutoPtr<IPipelineState> pPSO;
+ RefCntAutoPtr<IShaderResourceBinding> pSRB;
+ CreateDrawTrisPSO(pRenderPass, 1, pPSO, pSRB);
+ ASSERT_TRUE(pPSO != nullptr && pSRB != nullptr);
+
+ RefCntAutoPtr<IPipelineState> pInputAttachmentPSO;
+ RefCntAutoPtr<IShaderResourceBinding> pInputAttachmentSRB;
+ {
+ PipelineStateCreateInfo PSOCreateInfo;
+ PipelineStateDesc& PSODesc = PSOCreateInfo.PSODesc;
+
+ PSODesc.Name = "Render pass test - input attachment";
+
+ PSODesc.IsComputePipeline = false;
+ PSODesc.GraphicsPipeline.pRenderPass = pRenderPass;
+ PSODesc.GraphicsPipeline.SubpassIndex = 1;
+ PSODesc.GraphicsPipeline.SmplDesc.Count = 1;
+ PSODesc.GraphicsPipeline.PrimitiveTopology = PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ PSODesc.GraphicsPipeline.RasterizerDesc.CullMode = CULL_MODE_NONE;
+ PSODesc.GraphicsPipeline.DepthStencilDesc.DepthEnable = False;
+
+ ShaderCreateInfo ShaderCI;
+ ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_GLSL_VERBATIM;
+ ShaderCI.UseCombinedTextureSamplers = true;
+
+ RefCntAutoPtr<IShader> pVS;
+ {
+ ShaderCI.Desc.ShaderType = SHADER_TYPE_VERTEX;
+ ShaderCI.EntryPoint = "main";
+ ShaderCI.Desc.Name = "Input attachment test VS";
+ ShaderCI.Source = GLSL::DrawTest_ProceduralTriangleVS.c_str();
+ pDevice->CreateShader(ShaderCI, &pVS);
+ ASSERT_NE(pVS, nullptr);
+ }
+
+ RefCntAutoPtr<IShader> pPS;
+ {
+ ShaderCI.Desc.ShaderType = SHADER_TYPE_PIXEL;
+ ShaderCI.EntryPoint = "main";
+ ShaderCI.Desc.Name = "Input attachment test PS";
+ ShaderCI.Source = GLSL::InputAttachmentTest_FS.c_str();
+ pDevice->CreateShader(ShaderCI, &pPS);
+ ASSERT_NE(pPS, nullptr);
+ }
+
+ PSODesc.GraphicsPipeline.pVS = pVS;
+ PSODesc.GraphicsPipeline.pPS = pPS;
+
+ pDevice->CreatePipelineState(PSOCreateInfo, &pInputAttachmentPSO);
+ ASSERT_NE(pInputAttachmentPSO, nullptr);
+ pInputAttachmentPSO->GetStaticVariableByName(SHADER_TYPE_PIXEL, "in_Color")->Set(pTex->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE));
+ pInputAttachmentPSO->CreateShaderResourceBinding(&pInputAttachmentSRB, true);
+ ASSERT_NE(pInputAttachmentSRB, nullptr);
+ pContext->TransitionShaderResources(pInputAttachmentPSO, pInputAttachmentSRB);
+ }
+
+ ITextureView* pRTAttachments[] = //
+ {
+ pTex->GetDefaultView(TEXTURE_VIEW_RENDER_TARGET),
+ pSwapChain->GetCurrentBackBufferRTV() //
+ };
+
+ FramebufferDesc FBDesc;
+ FBDesc.Name = "Render pass input attachment test framebuffer";
+ FBDesc.pRenderPass = pRenderPass;
+ FBDesc.AttachmentCount = _countof(Attachments);
+ FBDesc.ppAttachments = pRTAttachments;
+ RefCntAutoPtr<IFramebuffer> pFramebuffer;
+ pDevice->CreateFramebuffer(FBDesc, &pFramebuffer);
+ ASSERT_TRUE(pFramebuffer);
+
+ pContext->SetPipelineState(pPSO);
+ pContext->CommitShaderResources(pSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
+
+ BeginRenderPassAttribs RPBeginInfo;
+ RPBeginInfo.pRenderPass = pRenderPass;
+ RPBeginInfo.pFramebuffer = pFramebuffer;
+
+ OptimizedClearValue ClearValues[2];
+ ClearValues[0].Color[0] = 0;
+ ClearValues[0].Color[1] = 0;
+ ClearValues[0].Color[2] = 0;
+ ClearValues[0].Color[3] = 0;
+
+ ClearValues[1].Color[0] = ClearColor[0];
+ ClearValues[1].Color[1] = ClearColor[1];
+ ClearValues[1].Color[2] = ClearColor[2];
+ ClearValues[1].Color[3] = ClearColor[3];
+
+ RPBeginInfo.pClearValues = ClearValues;
+ RPBeginInfo.ClearValueCount = _countof(ClearValues);
+ RPBeginInfo.StateTransitionMode = RESOURCE_STATE_TRANSITION_MODE_TRANSITION;
+ pContext->BeginRenderPass(RPBeginInfo);
+
+ DrawAttribs DrawAttrs{6, DRAW_FLAG_VERIFY_ALL};
+ pContext->Draw(DrawAttrs);
+
+ pContext->NextSubpass();
+
+ pContext->SetPipelineState(pInputAttachmentPSO);
+ pContext->CommitShaderResources(pInputAttachmentSRB, RESOURCE_STATE_TRANSITION_MODE_VERIFY);
+
+ pContext->Draw(DrawAttrs);
+
+ pContext->EndRenderPass(true);
+
+ Present();
}
} // namespace
diff --git a/Tests/DiligentCoreAPITest/src/TestingEnvironment.cpp b/Tests/DiligentCoreAPITest/src/TestingEnvironment.cpp
index 1896ba60..e0561f34 100644
--- a/Tests/DiligentCoreAPITest/src/TestingEnvironment.cpp
+++ b/Tests/DiligentCoreAPITest/src/TestingEnvironment.cpp
@@ -303,8 +303,8 @@ TestingEnvironment::TestingEnvironment(RENDER_DEVICE_TYPE deviceType, ADAPTER_TY
EngineVkCreateInfo CreateInfo;
CreateInfo.DebugMessageCallback = MessageCallback;
CreateInfo.EnableValidation = true;
- CreateInfo.MainDescriptorPoolSize = VulkanDescriptorPoolSize{64, 64, 256, 256, 64, 32, 32, 32, 32};
- CreateInfo.DynamicDescriptorPoolSize = VulkanDescriptorPoolSize{64, 64, 256, 256, 64, 32, 32, 32, 32};
+ CreateInfo.MainDescriptorPoolSize = VulkanDescriptorPoolSize{64, 64, 256, 256, 64, 32, 32, 32, 32, 16};
+ CreateInfo.DynamicDescriptorPoolSize = VulkanDescriptorPoolSize{64, 64, 256, 256, 64, 32, 32, 32, 32, 16};
CreateInfo.UploadHeapPageSize = 32 * 1024;
//CreateInfo.DeviceLocalMemoryReserveSize = 32 << 20;
//CreateInfo.HostVisibleMemoryReserveSize = 48 << 20;
diff --git a/Tests/DiligentCoreAPITest/src/Vulkan/DrawCommandReferenceVk.cpp b/Tests/DiligentCoreAPITest/src/Vulkan/DrawCommandReferenceVk.cpp
index 2ee67755..6084402f 100644
--- a/Tests/DiligentCoreAPITest/src/Vulkan/DrawCommandReferenceVk.cpp
+++ b/Tests/DiligentCoreAPITest/src/Vulkan/DrawCommandReferenceVk.cpp
@@ -47,7 +47,10 @@ namespace
struct ReferenceTriangleRenderer
{
- ReferenceTriangleRenderer(ISwapChain* pSwapChain, VkRenderPass vkRenderPass, VkSampleCountFlagBits SampleCount = VK_SAMPLE_COUNT_1_BIT)
+ ReferenceTriangleRenderer(ISwapChain* pSwapChain,
+ VkRenderPass vkRenderPass,
+ VkSampleCountFlagBits SampleCount = VK_SAMPLE_COUNT_1_BIT,
+ VkImageView InputAttachmentView = VK_NULL_HANDLE)
{
auto* pEnv = TestingEnvironmentVk::GetInstance();
auto vkDevice = pEnv->GetVkDevice();
@@ -59,7 +62,7 @@ struct ReferenceTriangleRenderer
vkVSModule = pEnv->CreateShaderModule(SHADER_TYPE_VERTEX, GLSL::DrawTest_ProceduralTriangleVS);
VERIFY_EXPR(vkVSModule != VK_NULL_HANDLE);
- vkPSModule = pEnv->CreateShaderModule(SHADER_TYPE_PIXEL, GLSL::DrawTest_FS);
+ vkPSModule = pEnv->CreateShaderModule(SHADER_TYPE_PIXEL, InputAttachmentView != VK_NULL_HANDLE ? GLSL::InputAttachmentTest_FS : GLSL::DrawTest_FS);
VERIFY_EXPR(vkPSModule != VK_NULL_HANDLE);
VkGraphicsPipelineCreateInfo PipelineCI = {};
@@ -85,8 +88,76 @@ struct ReferenceTriangleRenderer
VkPipelineLayoutCreateInfo PipelineLayoutCI = {};
PipelineLayoutCI.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+
+ VkDescriptorSetLayout vkSetLayout[1] = {};
+ if (InputAttachmentView != VK_NULL_HANDLE)
+ {
+ VkDescriptorSetLayoutBinding Bindings[1] = {};
+ Bindings[0].binding = 0;
+ Bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
+ Bindings[0].descriptorCount = 1;
+ Bindings[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
+ Bindings[0].pImmutableSamplers = nullptr;
+
+ VkDescriptorSetLayoutCreateInfo SetLayoutCI = {};
+
+ SetLayoutCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
+ SetLayoutCI.pNext = nullptr;
+ SetLayoutCI.flags = 0;
+ SetLayoutCI.bindingCount = 1;
+ SetLayoutCI.pBindings = Bindings;
+
+ vkCreateDescriptorSetLayout(vkDevice, &SetLayoutCI, nullptr, &vkSetLayout[0]);
+ VERIFY_EXPR(vkSetLayout[0] != VK_NULL_HANDLE);
+
+ PipelineLayoutCI.setLayoutCount = 1;
+ PipelineLayoutCI.pSetLayouts = vkSetLayout;
+
+ VkDescriptorPoolCreateInfo DescriptorPoolCI = {};
+ DescriptorPoolCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+ DescriptorPoolCI.pNext = nullptr;
+ DescriptorPoolCI.flags = 0;
+ DescriptorPoolCI.maxSets = 1;
+ VkDescriptorPoolSize PoolSizes[] = {{VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1}};
+ DescriptorPoolCI.poolSizeCount = _countof(PoolSizes);
+ DescriptorPoolCI.pPoolSizes = PoolSizes;
+
+ vkCreateDescriptorPool(vkDevice, &DescriptorPoolCI, nullptr, &vkDescriptorPool);
+ VERIFY_EXPR(vkDescriptorPool != VK_NULL_HANDLE);
+
+ VkDescriptorSetAllocateInfo SetAllocateInfo = {};
+ SetAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
+ SetAllocateInfo.pNext = nullptr;
+ SetAllocateInfo.descriptorPool = vkDescriptorPool;
+ SetAllocateInfo.descriptorSetCount = 1;
+ SetAllocateInfo.pSetLayouts = vkSetLayout;
+
+ vkAllocateDescriptorSets(vkDevice, &SetAllocateInfo, &vkDescriptorSet);
+ VERIFY_EXPR(vkDescriptorSet != VK_NULL_HANDLE);
+
+ VkWriteDescriptorSet DescriptorWrites[1] = {};
+
+ DescriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ DescriptorWrites[0].pNext = nullptr;
+ DescriptorWrites[0].dstSet = vkDescriptorSet;
+ DescriptorWrites[0].dstBinding = 0;
+ DescriptorWrites[0].dstArrayElement = 0;
+ DescriptorWrites[0].descriptorCount = 1;
+ DescriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
+ VkDescriptorImageInfo ImageInfo[1] = {};
+ ImageInfo[0].sampler = VK_NULL_HANDLE;
+ ImageInfo[0].imageView = InputAttachmentView;
+ ImageInfo[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ DescriptorWrites[0].pImageInfo = ImageInfo;
+
+ vkUpdateDescriptorSets(vkDevice, 1, DescriptorWrites, 0, nullptr);
+ }
vkCreatePipelineLayout(vkDevice, &PipelineLayoutCI, nullptr, &vkLayout);
VERIFY_EXPR(vkLayout != VK_NULL_HANDLE);
+ if (vkSetLayout[0] != VK_NULL_HANDLE)
+ {
+ vkDestroyDescriptorSetLayout(vkDevice, vkSetLayout[0], nullptr);
+ }
PipelineCI.layout = vkLayout;
VkPipelineVertexInputStateCreateInfo VertexInputStateCI = {};
@@ -191,7 +262,7 @@ struct ReferenceTriangleRenderer
PipelineCI.pDynamicState = &DynamicStateCI;
PipelineCI.renderPass = vkRenderPass;
- PipelineCI.subpass = 0;
+ PipelineCI.subpass = InputAttachmentView != VK_NULL_HANDLE ? 1 : 0;
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
@@ -202,6 +273,8 @@ struct ReferenceTriangleRenderer
void Draw(VkCommandBuffer vkCmdBuffer)
{
+ if (vkDescriptorSet != VK_NULL_HANDLE)
+ vkCmdBindDescriptorSets(vkCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vkLayout, 0, 1, &vkDescriptorSet, 0, nullptr);
vkCmdBindPipeline(vkCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vkPipeline);
vkCmdDraw(vkCmdBuffer, 6, 1, 0, 0);
}
@@ -215,13 +288,17 @@ struct ReferenceTriangleRenderer
vkDestroyPipelineLayout(vkDevice, vkLayout, nullptr);
vkDestroyShaderModule(vkDevice, vkVSModule, nullptr);
vkDestroyShaderModule(vkDevice, vkPSModule, nullptr);
+ if (vkDescriptorPool != VK_NULL_HANDLE)
+ vkDestroyDescriptorPool(vkDevice, vkDescriptorPool, nullptr);
}
private:
- VkShaderModule vkVSModule = VK_NULL_HANDLE;
- VkShaderModule vkPSModule = VK_NULL_HANDLE;
- VkPipeline vkPipeline = VK_NULL_HANDLE;
- VkPipelineLayout vkLayout = VK_NULL_HANDLE;
+ VkShaderModule vkVSModule = VK_NULL_HANDLE;
+ VkShaderModule vkPSModule = VK_NULL_HANDLE;
+ VkPipeline vkPipeline = VK_NULL_HANDLE;
+ VkPipelineLayout vkLayout = VK_NULL_HANDLE;
+ VkDescriptorPool vkDescriptorPool = VK_NULL_HANDLE;
+ VkDescriptorSet vkDescriptorSet = VK_NULL_HANDLE;
};
} // namespace
@@ -290,8 +367,8 @@ void RenderPassMSResolveReferenceVk(ISwapChain* pSwapChain, const float* pClearC
Attachments[1].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- VkAttachmentReference ColorAttachmentRef[1] = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
- VkAttachmentReference RslvAttachmentRef[1] = {1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
+ VkAttachmentReference ColorAttachmentRef[] = {{0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}};
+ VkAttachmentReference RslvAttachmentRef[] = {{1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}};
VkSubpassDescription Subpasses[1] = {};
Subpasses[0].flags = 0;
@@ -384,9 +461,8 @@ void RenderPassMSResolveReferenceVk(ISwapChain* pSwapChain, const float* pClearC
BeginInfo.pClearValues = ClearValues;
vkCmdBeginRenderPass(vkCmdBuffer, &BeginInfo, VK_SUBPASS_CONTENTS_INLINE);
-
TriRenderer.Draw(vkCmdBuffer);
- pTestingSwapChainVk->EndRenderPass(vkCmdBuffer);
+ vkCmdEndRenderPass(vkCmdBuffer);
vkEndCommandBuffer(vkCmdBuffer);
pEnv->SubmitCommandBuffer(vkCmdBuffer, true);
@@ -396,8 +472,177 @@ void RenderPassMSResolveReferenceVk(ISwapChain* pSwapChain, const float* pClearC
void RenderPassInputAttachmentReferenceVk(ISwapChain* pSwapChain, const float* pClearColor)
{
-}
+ auto* pEnv = TestingEnvironmentVk::GetInstance();
+ auto* pDevice = pEnv->GetDevice();
+ auto vkDevice = pEnv->GetVkDevice();
+
+ auto* pTestingSwapChainVk = ValidatedCast<TestingSwapChainVk>(pSwapChain);
+ const auto& SCDesc = pTestingSwapChainVk->GetDesc();
+
+ VkRenderPassCreateInfo RenderPassCI = {};
+
+ RenderPassCI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+ RenderPassCI.pNext = nullptr;
+ RenderPassCI.flags = 0; // reserved for future use
+ RenderPassCI.attachmentCount = 2;
+
+ VkAttachmentDescription Attachments[2] = {};
+
+ Attachments[0].flags = 0;
+ Attachments[0].samples = VK_SAMPLE_COUNT_1_BIT;
+ Attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ Attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ Attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ Attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ Attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ Attachments[0].finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ switch (SCDesc.ColorBufferFormat)
+ {
+ case TEX_FORMAT_RGBA8_UNORM:
+ Attachments[0].format = VK_FORMAT_R8G8B8A8_UNORM;
+ break;
+
+ default:
+ UNSUPPORTED("Unsupported swap chain format");
+ }
+
+ Attachments[1].flags = 0;
+ Attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
+ Attachments[1].format = Attachments[0].format;
+ Attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ Attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ Attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ Attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ Attachments[1].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ Attachments[1].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+ VkAttachmentReference ColorAttachmentRef0[] = {{0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}};
+ VkAttachmentReference InputAttachmentRef1[] = {{0, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL}};
+ VkAttachmentReference ColorAttachmentRef1[] = {{1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}};
+
+ VkSubpassDescription Subpasses[2] = {};
+ Subpasses[0].flags = 0;
+ Subpasses[0].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ Subpasses[0].colorAttachmentCount = _countof(ColorAttachmentRef0);
+ Subpasses[0].pColorAttachments = ColorAttachmentRef0;
+
+ Subpasses[1].flags = 0;
+ Subpasses[1].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ Subpasses[1].colorAttachmentCount = _countof(ColorAttachmentRef1);
+ Subpasses[1].pColorAttachments = ColorAttachmentRef1;
+ Subpasses[1].inputAttachmentCount = _countof(InputAttachmentRef1);
+ Subpasses[1].pInputAttachments = InputAttachmentRef1;
+
+ VkSubpassDependency dependencies[1] = {};
+ dependencies[0].srcSubpass = 0;
+ dependencies[0].dstSubpass = 1;
+ dependencies[0].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ dependencies[0].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ dependencies[0].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ dependencies[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+
+ RenderPassCI.attachmentCount = _countof(Attachments);
+ RenderPassCI.pAttachments = Attachments;
+ RenderPassCI.subpassCount = _countof(Subpasses);
+ RenderPassCI.pSubpasses = Subpasses;
+ RenderPassCI.dependencyCount = _countof(dependencies);
+ RenderPassCI.pDependencies = dependencies;
+
+ VkRenderPass vkRenderPass = VK_NULL_HANDLE;
+ vkCreateRenderPass(vkDevice, &RenderPassCI, nullptr, &vkRenderPass);
+ ASSERT_TRUE(vkRenderPass != VK_NULL_HANDLE);
+
+ ReferenceTriangleRenderer TriRenderer{pSwapChain, vkRenderPass};
+ RefCntAutoPtr<ITexture> pTex;
+ {
+ TextureDesc TexDesc;
+ TexDesc.Type = RESOURCE_DIM_TEX_2D;
+ TexDesc.Format = SCDesc.ColorBufferFormat;
+ TexDesc.Width = SCDesc.Width;
+ TexDesc.Height = SCDesc.Height;
+ TexDesc.BindFlags = BIND_RENDER_TARGET | BIND_INPUT_ATTACHMENT;
+ TexDesc.MipLevels = 1;
+ TexDesc.Usage = USAGE_DEFAULT;
+
+ pDevice->CreateTexture(TexDesc, nullptr, &pTex);
+ ASSERT_NE(pTex, nullptr);
+ }
+ RefCntAutoPtr<ITextureVk> pTexVK{pTex, IID_TextureVk};
+ ASSERT_NE(pTexVK, nullptr);
+ RefCntAutoPtr<ITextureViewVk> pTexViewVK{pTex->GetDefaultView(TEXTURE_VIEW_RENDER_TARGET), IID_TextureViewVk};
+ ASSERT_NE(pTexViewVK, nullptr);
+
+ ReferenceTriangleRenderer TriRenderer2{pSwapChain, vkRenderPass, VK_SAMPLE_COUNT_1_BIT, pTexViewVK->GetVulkanImageView()};
+
+ VkFramebufferCreateInfo FramebufferCI = {};
+
+ FramebufferCI.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+ FramebufferCI.pNext = nullptr;
+ FramebufferCI.flags = 0;
+ FramebufferCI.renderPass = vkRenderPass;
+
+ VkImageView FramebufferAttachments[2];
+ FramebufferAttachments[0] = pTexViewVK->GetVulkanImageView();
+ FramebufferAttachments[1] = pTestingSwapChainVk->GetVkRenderTargetImageView();
+ FramebufferCI.pAttachments = FramebufferAttachments;
+ FramebufferCI.attachmentCount = _countof(FramebufferAttachments);
+
+ FramebufferCI.width = SCDesc.Width;
+ FramebufferCI.height = SCDesc.Height;
+ FramebufferCI.layers = 1;
+
+ VkFramebuffer vkFramebuffer = VK_NULL_HANDLE;
+ vkCreateFramebuffer(vkDevice, &FramebufferCI, nullptr, &vkFramebuffer);
+ ASSERT_TRUE(vkFramebuffer != VK_NULL_HANDLE);
+
+ VkCommandBuffer vkCmdBuffer = pEnv->AllocateCommandBuffer();
+ pTestingSwapChainVk->TransitionRenderTarget(vkCmdBuffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
+ {
+ auto CurrLayout = pTexVK->GetLayout();
+
+ VkImageSubresourceRange SubResRange;
+ SubResRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ SubResRange.baseMipLevel = 0;
+ SubResRange.levelCount = 1;
+ SubResRange.baseArrayLayer = 0;
+ SubResRange.layerCount = 1;
+ pEnv->TransitionImageLayout(vkCmdBuffer, pTexVK->GetVkImage(), CurrLayout, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, SubResRange, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
+ }
+
+ VkRenderPassBeginInfo BeginInfo = {};
+
+ BeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ BeginInfo.renderPass = vkRenderPass;
+ BeginInfo.framebuffer = vkFramebuffer;
+ BeginInfo.renderArea.extent = VkExtent2D{SCDesc.Width, SCDesc.Height};
+
+ VkClearValue ClearValues[2] = {};
+ ClearValues[0].color.float32[0] = 0;
+ ClearValues[0].color.float32[1] = 0;
+ ClearValues[0].color.float32[2] = 0;
+ ClearValues[0].color.float32[3] = 0;
+
+ ClearValues[1].color.float32[0] = pClearColor[0];
+ ClearValues[1].color.float32[1] = pClearColor[1];
+ ClearValues[1].color.float32[2] = pClearColor[2];
+ ClearValues[1].color.float32[3] = pClearColor[3];
+
+ BeginInfo.clearValueCount = _countof(ClearValues);
+ BeginInfo.pClearValues = ClearValues;
+
+ vkCmdBeginRenderPass(vkCmdBuffer, &BeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+
+ TriRenderer.Draw(vkCmdBuffer);
+ vkCmdNextSubpass(vkCmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
+ TriRenderer2.Draw(vkCmdBuffer);
+ vkCmdEndRenderPass(vkCmdBuffer);
+ vkEndCommandBuffer(vkCmdBuffer);
+ pEnv->SubmitCommandBuffer(vkCmdBuffer, true);
+
+ vkDestroyRenderPass(vkDevice, vkRenderPass, nullptr);
+ vkDestroyFramebuffer(vkDevice, vkFramebuffer, nullptr);
+}
} // namespace Testing