Skip to content

Commit bbbc402

Browse files
Vulkan: added dynamic rendering support in device and pipeline state
1 parent 3d93ba0 commit bbbc402

File tree

8 files changed

+120
-63
lines changed

8 files changed

+120
-63
lines changed

Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019-2023 Diligent Graphics LLC
2+
* Copyright 2019-2025 Diligent Graphics LLC
33
* Copyright 2015-2019 Egor Yusov
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -233,8 +233,8 @@ class RenderDeviceVkImpl final : public RenderDeviceNextGenBase<RenderDeviceBase
233233
const VulkanUtilities::VulkanPhysicalDevice& GetPhysicalDevice() const { return *m_PhysicalDevice; }
234234
const VulkanUtilities::VulkanLogicalDevice& GetLogicalDevice() const { return *m_LogicalVkDevice; }
235235

236-
FramebufferCache& GetFramebufferCache() { return m_FramebufferCache; }
237-
RenderPassCache& GetImplicitRenderPassCache() { return m_ImplicitRenderPassCache; }
236+
FramebufferCache* GetFramebufferCache() { return m_FramebufferCache.get(); }
237+
RenderPassCache* GetImplicitRenderPassCache() { return m_ImplicitRenderPassCache.get(); }
238238

239239
VulkanUtilities::VulkanMemoryAllocation AllocateMemory(const VkMemoryRequirements& MemReqs, VkMemoryPropertyFlags MemoryProperties, VkMemoryAllocateFlags AllocateFlags = 0)
240240
{
@@ -295,8 +295,9 @@ class RenderDeviceVkImpl final : public RenderDeviceNextGenBase<RenderDeviceBase
295295
std::unique_ptr<VulkanUtilities::VulkanPhysicalDevice> m_PhysicalDevice;
296296
std::shared_ptr<VulkanUtilities::VulkanLogicalDevice> m_LogicalVkDevice;
297297

298-
FramebufferCache m_FramebufferCache;
299-
RenderPassCache m_ImplicitRenderPassCache;
298+
std::unique_ptr<FramebufferCache> m_FramebufferCache;
299+
std::unique_ptr<RenderPassCache> m_ImplicitRenderPassCache;
300+
300301
DescriptorSetAllocator m_DescriptorSetAllocator;
301302
DescriptorPoolManager m_DynamicDescriptorPool;
302303

Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019-2024 Diligent Graphics LLC
2+
* Copyright 2019-2025 Diligent Graphics LLC
33
* Copyright 2015-2019 Egor Yusov
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -67,6 +67,7 @@ class VulkanPhysicalDevice
6767
VkPhysicalDeviceMultiviewFeaturesKHR Multiview = {}; // Required for RenderPass2
6868
VkPhysicalDeviceMultiDrawFeaturesEXT MultiDraw = {};
6969
VkPhysicalDeviceShaderDrawParametersFeatures ShaderDrawParameters = {};
70+
VkPhysicalDeviceDynamicRenderingFeaturesKHR DynamicRendering = {};
7071

7172
bool Spirv14 = false; // Ray tracing requires Vulkan 1.2 or SPIRV 1.4 extension
7273
bool Spirv15 = false; // DXC shaders with ray tracing requires Vulkan 1.2 with SPIRV 1.5

Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1887,21 +1887,28 @@ void DeviceContextVkImpl::ChooseRenderPassAndFramebuffer()
18871887
RenderPassKey.EnableVRS = false;
18881888
}
18891889

1890-
auto& FBCache = m_pDevice->GetFramebufferCache();
1891-
auto& RPCache = m_pDevice->GetImplicitRenderPassCache();
1890+
FramebufferCache* FBCache = m_pDevice->GetFramebufferCache();
1891+
RenderPassCache* RPCache = m_pDevice->GetImplicitRenderPassCache();
18921892

1893-
if (auto* pRenderPass = RPCache.GetRenderPass(RenderPassKey))
1893+
if (FBCache != nullptr && RPCache != nullptr)
18941894
{
1895-
m_vkRenderPass = pRenderPass->GetVkRenderPass();
1896-
FBKey.Pass = m_vkRenderPass;
1897-
FBKey.CommandQueueMask = ~Uint64{0};
1898-
m_vkFramebuffer = FBCache.GetFramebuffer(FBKey, m_FramebufferWidth, m_FramebufferHeight, m_FramebufferSlices);
1895+
if (RenderPassVkImpl* pRenderPass = RPCache->GetRenderPass(RenderPassKey))
1896+
{
1897+
m_vkRenderPass = pRenderPass->GetVkRenderPass();
1898+
FBKey.Pass = m_vkRenderPass;
1899+
FBKey.CommandQueueMask = ~Uint64{0};
1900+
m_vkFramebuffer = FBCache->GetFramebuffer(FBKey, m_FramebufferWidth, m_FramebufferHeight, m_FramebufferSlices);
1901+
}
1902+
else
1903+
{
1904+
UNEXPECTED("Unable to get render pass for the currently bound render targets");
1905+
m_vkRenderPass = VK_NULL_HANDLE;
1906+
m_vkFramebuffer = VK_NULL_HANDLE;
1907+
}
18991908
}
19001909
else
19011910
{
1902-
UNEXPECTED("Unable to get render pass for the currently bound render targets");
1903-
m_vkRenderPass = VK_NULL_HANDLE;
1904-
m_vkFramebuffer = VK_NULL_HANDLE;
1911+
UNSUPPORTED("Dynamic rendering is not supported");
19051912
}
19061913
}
19071914

Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -137,20 +137,29 @@ void CreateGraphicsPipeline(RenderDeviceVkImpl* pDevic
137137
{
138138
const VulkanUtilities::VulkanLogicalDevice& LogicalDevice = pDeviceVk->GetLogicalDevice();
139139
const VulkanUtilities::VulkanPhysicalDevice& PhysicalDevice = pDeviceVk->GetPhysicalDevice();
140-
RenderPassCache& RPCache = pDeviceVk->GetImplicitRenderPassCache();
141140

141+
VkPipelineRenderingCreateInfoKHR PipelineRenderingCI{};
142+
std::vector<VkFormat> ColorAttachmentFormats;
142143
if (pRenderPass == nullptr)
143144
{
144-
RenderPassCache::RenderPassCacheKey Key{
145-
GraphicsPipeline.NumRenderTargets,
146-
GraphicsPipeline.SmplDesc.Count,
147-
GraphicsPipeline.RTVFormats,
148-
GraphicsPipeline.DSVFormat,
149-
(GraphicsPipeline.ShadingRateFlags & PIPELINE_SHADING_RATE_FLAG_TEXTURE_BASED) != 0,
150-
GraphicsPipeline.ReadOnlyDSV};
151-
pRenderPass = RPCache.GetRenderPass(Key);
152-
if (pRenderPass == nullptr)
153-
LOG_ERROR_AND_THROW("Failed to create default render pass.");
145+
if (RenderPassCache* RPCache = pDeviceVk->GetImplicitRenderPassCache())
146+
{
147+
RenderPassCache::RenderPassCacheKey Key{
148+
GraphicsPipeline.NumRenderTargets,
149+
GraphicsPipeline.SmplDesc.Count,
150+
GraphicsPipeline.RTVFormats,
151+
GraphicsPipeline.DSVFormat,
152+
(GraphicsPipeline.ShadingRateFlags & PIPELINE_SHADING_RATE_FLAG_TEXTURE_BASED) != 0,
153+
GraphicsPipeline.ReadOnlyDSV};
154+
pRenderPass = RPCache->GetRenderPass(Key);
155+
if (pRenderPass == nullptr)
156+
LOG_ERROR_AND_THROW("Failed to create default render pass.");
157+
}
158+
else
159+
{
160+
// VK_KHR_dynamic_rendering
161+
PipelineRenderingCI = GraphicsPipelineDesc_To_VkPipelineRenderingCreateInfo(GraphicsPipeline, ColorAttachmentFormats);
162+
}
154163
}
155164

156165
VkGraphicsPipelineCreateInfo PipelineCI{};
@@ -270,9 +279,17 @@ void CreateGraphicsPipeline(RenderDeviceVkImpl* pDevic
270279
DepthStencilStateDesc_To_VkDepthStencilStateCI(GraphicsPipeline.DepthStencilDesc);
271280
PipelineCI.pDepthStencilState = &DepthStencilStateCI;
272281

273-
const RenderPassDesc& RPDesc = pRenderPass->GetDesc();
274-
const Uint32 NumRTAttachments = RPDesc.pSubpasses[GraphicsPipeline.SubpassIndex].RenderTargetAttachmentCount;
275-
VERIFY_EXPR(GraphicsPipeline.pRenderPass != nullptr || GraphicsPipeline.NumRenderTargets == NumRTAttachments);
282+
Uint32 NumRTAttachments = 0;
283+
if (pRenderPass != nullptr)
284+
{
285+
const RenderPassDesc& RPDesc = pRenderPass->GetDesc();
286+
NumRTAttachments = RPDesc.pSubpasses[GraphicsPipeline.SubpassIndex].RenderTargetAttachmentCount;
287+
VERIFY_EXPR(GraphicsPipeline.pRenderPass != nullptr || GraphicsPipeline.NumRenderTargets == NumRTAttachments);
288+
}
289+
else
290+
{
291+
NumRTAttachments = PipelineRenderingCI.colorAttachmentCount;
292+
}
276293
std::vector<VkPipelineColorBlendAttachmentState> ColorBlendAttachmentStates(NumRTAttachments);
277294

278295
VkPipelineColorBlendStateCreateInfo BlendStateCI{};
@@ -324,7 +341,14 @@ void CreateGraphicsPipeline(RenderDeviceVkImpl* pDevic
324341
PipelineCI.pDynamicState = &DynamicStateCI;
325342

326343

327-
PipelineCI.renderPass = pRenderPass.RawPtr<IRenderPassVk>()->GetVkRenderPass();
344+
if (pRenderPass)
345+
{
346+
PipelineCI.renderPass = pRenderPass.RawPtr<IRenderPassVk>()->GetVkRenderPass();
347+
}
348+
else
349+
{
350+
PipelineCI.pNext = &PipelineRenderingCI;
351+
}
328352
PipelineCI.subpass = GraphicsPipeline.SubpassIndex;
329353
PipelineCI.basePipelineHandle = VK_NULL_HANDLE; // a pipeline to derive from
330354
PipelineCI.basePipelineIndex = -1; // an index into the pCreateInfos parameter to use as a pipeline to derive from
@@ -571,7 +595,7 @@ PipelineResourceSignatureDescWrapper PipelineStateVkImpl::GetDefaultResourceSign
571595
std::unordered_map<ShaderResourceHashKey, const SPIRVShaderResourceAttribs&, ShaderResourceHashKey::Hasher> UniqueResources;
572596
for (const ShaderStageInfo& Stage : ShaderStages)
573597
{
574-
for (auto* pShader : Stage.Shaders)
598+
for (const ShaderVkImpl* pShader : Stage.Shaders)
575599
{
576600
const SPIRVShaderResources& ShaderResources = *pShader->GetShaderResources();
577601
ShaderResources.ProcessResources(
@@ -662,7 +686,7 @@ void PipelineStateVkImpl::RemapOrVerifyShaderResources(
662686
pShaderResources->ProcessResources(
663687
[&](const SPIRVShaderResourceAttribs& SPIRVAttribs, Uint32) //
664688
{
665-
const auto ResAttribution = GetResourceAttribution(SPIRVAttribs.Name, ShaderType, pSignatures, SignatureCount);
689+
const ResourceAttribution ResAttribution = GetResourceAttribution(SPIRVAttribs.Name, ShaderType, pSignatures, SignatureCount);
666690
if (!ResAttribution)
667691
{
668692
LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource '", SPIRVAttribs.Name,

Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,6 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters*
7979
m_VulkanInstance {Instance },
8080
m_PhysicalDevice {std::move(PhysicalDevice)},
8181
m_LogicalVkDevice {std::move(LogicalDevice) },
82-
m_FramebufferCache {*this },
83-
m_ImplicitRenderPassCache{*this },
8482
m_DescriptorSetAllocator
8583
{
8684
*this,
@@ -146,6 +144,12 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters*
146144
m_pDxCompiler{CreateDXCompiler(DXCompilerTarget::Vulkan, m_PhysicalDevice->GetVkVersion(), EngineCI.pDxCompilerPath)}
147145
// clang-format on
148146
{
147+
if (!m_LogicalVkDevice->GetEnabledExtFeatures().DynamicRendering.dynamicRendering)
148+
{
149+
m_FramebufferCache = std::make_unique<FramebufferCache>(*this);
150+
m_ImplicitRenderPassCache = std::make_unique<RenderPassCache>(*this);
151+
}
152+
149153
static_assert(sizeof(VulkanDescriptorPoolSize) == sizeof(Uint32) * 11, "Please add new descriptors to m_DescriptorSetAllocator and m_DynamicDescriptorPool constructors");
150154

151155
const uint32_t vkVersion = m_PhysicalDevice->GetVkVersion();
@@ -204,7 +208,10 @@ RenderDeviceVkImpl::~RenderDeviceVkImpl()
204208
m_DynamicMemoryManager.Destroy();
205209

206210
// Explicitly destroy render pass cache
207-
m_ImplicitRenderPassCache.Destroy();
211+
if (m_ImplicitRenderPassCache)
212+
{
213+
m_ImplicitRenderPassCache->Destroy();
214+
}
208215

209216
// Wait for the GPU to complete all its operations
210217
IdleGPU();
@@ -454,7 +461,7 @@ void RenderDeviceVkImpl::ReleaseStaleResources(bool ForceRelease)
454461

455462
void RenderDeviceVkImpl::TestTextureFormat(TEXTURE_FORMAT TexFormat)
456463
{
457-
auto& TexFormatInfo = m_TextureFormatsInfo[TexFormat];
464+
TextureFormatInfoExt& TexFormatInfo = m_TextureFormatsInfo[TexFormat];
458465
VERIFY(TexFormatInfo.Supported, "Texture format is not supported");
459466

460467
VkPhysicalDevice vkPhysicalDevice = m_PhysicalDevice->GetVkDeviceHandle();

Graphics/GraphicsEngineVulkan/src/RenderPassCache.cpp

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019-2023 Diligent Graphics LLC
2+
* Copyright 2019-2025 Diligent Graphics LLC
33
* Copyright 2015-2019 Egor Yusov
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -53,10 +53,16 @@ RenderPassCache::~RenderPassCache()
5353

5454
void RenderPassCache::Destroy()
5555
{
56-
auto& FBCache = m_DeviceVkImpl.GetFramebufferCache();
57-
for (auto it = m_Cache.begin(); it != m_Cache.end(); ++it)
56+
if (FramebufferCache* FBCache = m_DeviceVkImpl.GetFramebufferCache())
5857
{
59-
FBCache.OnDestroyRenderPass(it->second->GetVkRenderPass());
58+
for (auto it = m_Cache.begin(); it != m_Cache.end(); ++it)
59+
{
60+
FBCache->OnDestroyRenderPass(it->second->GetVkRenderPass());
61+
}
62+
}
63+
else
64+
{
65+
UNEXPECTED("Framebuffer cache must not be null");
6066
}
6167
m_Cache.clear();
6268
}
@@ -78,14 +84,14 @@ static RenderPassDesc GetImplicitRenderPassDesc(
7884

7985
RenderPassDesc RPDesc;
8086

81-
auto& AttachmentInd{RPDesc.AttachmentCount};
87+
Uint32& AttachmentInd{RPDesc.AttachmentCount};
8288

8389
AttachmentReference* pDepthAttachmentReference = nullptr;
8490
if (DSVFormat != TEX_FORMAT_UNKNOWN)
8591
{
8692
const RESOURCE_STATE DepthAttachmentState = ReadOnlyDepth ? RESOURCE_STATE_DEPTH_READ : RESOURCE_STATE_DEPTH_WRITE;
8793

88-
auto& DepthAttachment = Attachments[AttachmentInd];
94+
RenderPassAttachmentDesc& DepthAttachment = Attachments[AttachmentInd];
8995

9096
DepthAttachment.Format = DSVFormat;
9197
DepthAttachment.SampleCount = SampleCount;
@@ -110,15 +116,15 @@ static RenderPassDesc GetImplicitRenderPassDesc(
110116
AttachmentReference* pColorAttachmentsReference = NumRenderTargets > 0 ? &AttachmentReferences[AttachmentInd] : nullptr;
111117
for (Uint32 rt = 0; rt < NumRenderTargets; ++rt)
112118
{
113-
auto& ColorAttachmentRef = pColorAttachmentsReference[rt];
119+
AttachmentReference& ColorAttachmentRef = pColorAttachmentsReference[rt];
114120

115121
if (RTVFormats[rt] == TEX_FORMAT_UNKNOWN)
116122
{
117123
ColorAttachmentRef.AttachmentIndex = ATTACHMENT_UNUSED;
118124
continue;
119125
}
120126

121-
auto& ColorAttachment = Attachments[AttachmentInd];
127+
RenderPassAttachmentDesc& ColorAttachment = Attachments[AttachmentInd];
122128

123129
ColorAttachment.Format = RTVFormats[rt];
124130
ColorAttachment.SampleCount = SampleCount;
@@ -141,7 +147,7 @@ static RenderPassDesc GetImplicitRenderPassDesc(
141147

142148
if (ShadingRateTexFormat != TEX_FORMAT_UNKNOWN)
143149
{
144-
auto& SRAttachment = Attachments[AttachmentInd];
150+
RenderPassAttachmentDesc& SRAttachment = Attachments[AttachmentInd];
145151

146152
SRAttachment.Format = ShadingRateTexFormat;
147153
SRAttachment.SampleCount = 1;
@@ -197,7 +203,7 @@ RenderPassVkImpl* RenderPassCache::GetRenderPass(const RenderPassCacheKey& Key)
197203
uint2 SRTileSize;
198204
if (Key.EnableVRS)
199205
{
200-
const auto& SRProps = m_DeviceVkImpl.GetAdapterInfo().ShadingRate;
206+
const ShadingRateProperties& SRProps = m_DeviceVkImpl.GetAdapterInfo().ShadingRate;
201207
switch (SRProps.Format)
202208
{
203209
case SHADING_RATE_FORMAT_PALETTE: SRFormat = TEX_FORMAT_R8_UINT; break;
@@ -211,8 +217,8 @@ RenderPassVkImpl* RenderPassCache::GetRenderPass(const RenderPassCacheKey& Key)
211217
SubpassDesc Subpass;
212218
ShadingRateAttachment ShadingRate;
213219

214-
auto RPDesc = GetImplicitRenderPassDesc(Key.NumRenderTargets, Key.RTVFormats, Key.DSVFormat, Key.ReadOnlyDSV, Key.SampleCount, SRFormat, SRTileSize,
215-
Attachments, AttachmentReferences, Subpass, ShadingRate);
220+
RenderPassDesc RPDesc = GetImplicitRenderPassDesc(Key.NumRenderTargets, Key.RTVFormats, Key.DSVFormat, Key.ReadOnlyDSV, Key.SampleCount,
221+
SRFormat, SRTileSize, Attachments, AttachmentReferences, Subpass, ShadingRate);
216222

217223
std::stringstream PassNameSS;
218224
PassNameSS << "Implicit render pass: RT count: " << Uint32{Key.NumRenderTargets} << "; sample count: " << Uint32{Key.SampleCount}
@@ -228,7 +234,7 @@ RenderPassVkImpl* RenderPassCache::GetRenderPass(const RenderPassCacheKey& Key)
228234
if (Key.EnableVRS)
229235
PassNameSS << "; VRS";
230236

231-
const auto PassName{PassNameSS.str()};
237+
const std::string PassName{PassNameSS.str()};
232238
RPDesc.Name = PassName.c_str();
233239

234240
RefCntAutoPtr<RenderPassVkImpl> pRenderPass;

Graphics/GraphicsEngineVulkan/src/TextureViewVkImpl.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019-2023 Diligent Graphics LLC
2+
* Copyright 2019-2025 Diligent Graphics LLC
33
* Copyright 2015-2019 Egor Yusov
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -55,12 +55,15 @@ TextureViewVkImpl::TextureViewVkImpl(IReferenceCounters* pRefCou
5555

5656
TextureViewVkImpl::~TextureViewVkImpl()
5757
{
58-
if (m_Desc.ViewType == TEXTURE_VIEW_DEPTH_STENCIL ||
59-
m_Desc.ViewType == TEXTURE_VIEW_READ_ONLY_DEPTH_STENCIL ||
60-
m_Desc.ViewType == TEXTURE_VIEW_RENDER_TARGET ||
61-
m_Desc.ViewType == TEXTURE_VIEW_SHADING_RATE)
58+
if (FramebufferCache* FBCache = m_pDevice->GetFramebufferCache())
6259
{
63-
m_pDevice->GetFramebufferCache().OnDestroyImageView(m_ImageView);
60+
if (m_Desc.ViewType == TEXTURE_VIEW_DEPTH_STENCIL ||
61+
m_Desc.ViewType == TEXTURE_VIEW_READ_ONLY_DEPTH_STENCIL ||
62+
m_Desc.ViewType == TEXTURE_VIEW_RENDER_TARGET ||
63+
m_Desc.ViewType == TEXTURE_VIEW_SHADING_RATE)
64+
{
65+
FBCache->OnDestroyImageView(m_ImageView);
66+
}
6467
}
6568
m_pDevice->SafeReleaseDeviceObject(std::move(m_ImageView), m_pTexture->GetDesc().ImmediateContextMask);
6669
}

0 commit comments

Comments
 (0)