Skip to content

Commit 477edd8

Browse files
DeviceContextVk: initial implementation of dynamic rendering
1 parent 59db520 commit 477edd8

File tree

8 files changed

+323
-42
lines changed

8 files changed

+323
-42
lines changed

Graphics/GraphicsEngineVulkan/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ set(INCLUDE
4848
)
4949

5050
set(VULKAN_UTILS_INCLUDE
51+
include/VulkanUtilities/RenderingInfoWrapper.hpp
5152
include/VulkanUtilities/VulkanCommandBuffer.hpp
5253
include/VulkanUtilities/VulkanCommandBufferPool.hpp
5354
include/VulkanUtilities/VulkanDebug.hpp
@@ -128,6 +129,7 @@ set(SRC
128129
)
129130

130131
set(VULKAN_UTILS_SRC
132+
src/VulkanUtilities/RenderingInfoWrapper.cpp
131133
src/VulkanUtilities/VulkanCommandBuffer.cpp
132134
src/VulkanUtilities/VulkanCommandBufferPool.cpp
133135
src/VulkanUtilities/VulkanDebug.cpp

Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp

Lines changed: 8 additions & 3 deletions
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");
@@ -52,6 +52,7 @@
5252
#include "VulkanUtilities/VulkanCommandBufferPool.hpp"
5353
#include "VulkanUtilities/VulkanCommandBuffer.hpp"
5454
#include "VulkanUtilities/VulkanSyncObjectManager.hpp"
55+
#include "VulkanUtilities/RenderingInfoWrapper.hpp"
5556
#include "VulkanUploadHeap.hpp"
5657
#include "VulkanDynamicHeap.hpp"
5758
#include "ResourceReleaseQueue.hpp"
@@ -449,7 +450,7 @@ class DeviceContextVkImpl final : public DeviceContextNextGenBase<EngineVkImplTr
449450
m_State.NumCommands = m_State.NumCommands != 0 ? m_State.NumCommands : 1;
450451
if (m_CommandBuffer.GetVkCmdBuffer() == VK_NULL_HANDLE)
451452
{
452-
auto vkCmdBuff = m_CmdPool->GetCommandBuffer();
453+
VkCommandBuffer vkCmdBuff = m_CmdPool->GetCommandBuffer();
453454
m_CommandBuffer.SetVkCmdBuffer(vkCmdBuff, m_CmdPool->GetSupportedStagesMask(), m_CmdPool->GetSupportedAccessMask());
454455
}
455456
}
@@ -489,6 +490,7 @@ class DeviceContextVkImpl final : public DeviceContextNextGenBase<EngineVkImplTr
489490

490491
void ChooseRenderPassAndFramebuffer();
491492

493+
private:
492494
VulkanUtilities::VulkanCommandBuffer m_CommandBuffer;
493495

494496
struct ContextState
@@ -558,7 +560,7 @@ class DeviceContextVkImpl final : public DeviceContextNextGenBase<EngineVkImplTr
558560
std::vector<Uint32> m_DynamicBufferOffsets;
559561

560562
/// Temporary array used by CommitDescriptorSets
561-
std::array<VkDescriptorSet, MAX_RESOURCE_SIGNATURES* MAX_DESCR_SET_PER_SIGNATURE> m_DescriptorSets = {};
563+
std::array<VkDescriptorSet, (MAX_RESOURCE_SIGNATURES * MAX_DESCR_SET_PER_SIGNATURE)> m_DescriptorSets = {};
562564

563565
/// Render pass that matches currently bound render targets.
564566
/// This render pass may or may not be currently set in the command buffer
@@ -568,6 +570,9 @@ class DeviceContextVkImpl final : public DeviceContextNextGenBase<EngineVkImplTr
568570
/// This framebuffer may or may not be currently set in the command buffer
569571
VkFramebuffer m_vkFramebuffer = VK_NULL_HANDLE;
570572

573+
/// Dynamic rendering info.
574+
std::unique_ptr<VulkanUtilities::RenderingInfoWrapper> m_DynamicRenderingInfo;
575+
571576
FixedBlockMemoryAllocator m_CmdListAllocator;
572577

573578
// Semaphores are not owned by the command context

Graphics/GraphicsEngineVulkan/include/FramebufferCache.hpp

Lines changed: 12 additions & 2 deletions
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");
@@ -32,8 +32,10 @@
3232

3333
#include <unordered_map>
3434
#include <mutex>
35+
#include <memory>
3536

3637
#include "VulkanUtilities/VulkanObjectWrappers.hpp"
38+
#include "VulkanUtilities/RenderingInfoWrapper.hpp"
3739

3840
namespace Diligent
3941
{
@@ -77,7 +79,15 @@ class FramebufferCache
7779
void OnDestroyImageView(VkImageView ImgView);
7880
void OnDestroyRenderPass(VkRenderPass Pass);
7981

80-
private:
82+
static std::unique_ptr<VulkanUtilities::RenderingInfoWrapper> CreateDyanmicRenderInfo(
83+
const FramebufferCacheKey& Key,
84+
bool UseDepthAttachment,
85+
bool UseStencilAttachment,
86+
uint32_t width,
87+
uint32_t height,
88+
uint32_t layers,
89+
uint32_t viewMask);
90+
8191
RenderDeviceVkImpl& m_DeviceVk;
8292

8393
struct FramebufferCacheKeyHash
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
* Copyright 2025 Diligent Graphics LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* In no event and under no legal theory, whether in tort (including negligence),
17+
* contract, or otherwise, unless required by applicable law (such as deliberate
18+
* and grossly negligent acts) or agreed to in writing, shall any Contributor be
19+
* liable for any damages, including any direct, indirect, special, incidental,
20+
* or consequential damages of any character arising as a result of this License or
21+
* out of the use or inability to use the software (including but not limited to damages
22+
* for loss of goodwill, work stoppage, computer failure or malfunction, or any and
23+
* all other commercial damages or losses), even if such Contributor has been advised
24+
* of the possibility of such damages.
25+
*/
26+
27+
#pragma once
28+
29+
#include <memory>
30+
31+
#include "VulkanHeaders.h"
32+
#include "DebugUtilities.hpp"
33+
34+
namespace VulkanUtilities
35+
{
36+
37+
class RenderingInfoWrapper
38+
{
39+
public:
40+
RenderingInfoWrapper(size_t Hash,
41+
uint32_t ColorAttachmentCount,
42+
bool UseDepthAttachment,
43+
bool UseStencilAttachment);
44+
45+
// clang-format off
46+
RenderingInfoWrapper (const RenderingInfoWrapper&) = delete;
47+
RenderingInfoWrapper (RenderingInfoWrapper&&) = delete;
48+
RenderingInfoWrapper& operator=(const RenderingInfoWrapper&) = delete;
49+
RenderingInfoWrapper& operator=(RenderingInfoWrapper&&) = delete;
50+
// clang-format on
51+
52+
operator const VkRenderingInfoKHR&() const { return m_RI; }
53+
54+
size_t GetHash() const { return m_Hash; }
55+
56+
RenderingInfoWrapper& SetFlags(VkRenderingFlagsKHR flags)
57+
{
58+
m_RI.flags = flags;
59+
return *this;
60+
}
61+
62+
RenderingInfoWrapper& SetRenderArea(const VkRect2D& renderArea)
63+
{
64+
m_RI.renderArea = renderArea;
65+
return *this;
66+
}
67+
68+
RenderingInfoWrapper& SetLayerCount(uint32_t layerCount)
69+
{
70+
m_RI.layerCount = layerCount;
71+
return *this;
72+
}
73+
74+
RenderingInfoWrapper& SetViewMask(uint32_t viewMask)
75+
{
76+
m_RI.viewMask = viewMask;
77+
return *this;
78+
}
79+
80+
VkRenderingAttachmentInfoKHR& GetColorAttachment(uint32_t Index)
81+
{
82+
VERIFY_EXPR(Index < m_RI.colorAttachmentCount);
83+
return m_Attachments[Index];
84+
}
85+
86+
VkRenderingAttachmentInfoKHR& GetDepthAttachment()
87+
{
88+
VERIFY_EXPR(m_RI.pDepthAttachment != nullptr && m_DepthAttachmentIndex != ~0u);
89+
return m_Attachments[m_DepthAttachmentIndex];
90+
}
91+
92+
VkRenderingAttachmentInfoKHR& GetStencilAttachment()
93+
{
94+
VERIFY_EXPR(m_RI.pStencilAttachment != nullptr && m_StencilAttachmentIndex != ~0u);
95+
return m_Attachments[m_StencilAttachmentIndex];
96+
}
97+
98+
private:
99+
VkRenderingInfoKHR m_RI;
100+
101+
const size_t m_Hash = 0;
102+
103+
std::unique_ptr<VkRenderingAttachmentInfoKHR[]> m_Attachments;
104+
105+
uint32_t m_DepthAttachmentIndex = ~0u;
106+
uint32_t m_StencilAttachmentIndex = ~0u;
107+
};
108+
109+
} // namespace VulkanUtilities

Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ class VulkanCommandBuffer
295295
{
296296
VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
297297
VERIFY(m_State.RenderPass == VK_NULL_HANDLE, "Current pass has not been ended");
298-
VERIFY(!m_State.RenderingBegan, "Current dynamic render pass has not been ended");
298+
VERIFY(m_State.DynamicRenderingHash == 0, "Current dynamic render pass has not been ended");
299299

300300
if (m_State.RenderPass != RenderPass || m_State.Framebuffer != Framebuffer)
301301
{
@@ -354,28 +354,34 @@ class VulkanCommandBuffer
354354
vkCmdNextSubpass(m_VkCmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
355355
}
356356

357-
__forceinline void BeginRendering(const VkRenderingInfoKHR& RenderingInfo)
357+
__forceinline void BeginRendering(const VkRenderingInfoKHR& RenderingInfo, size_t Hash)
358358
{
359359
VERIFY(m_State.RenderPass == VK_NULL_HANDLE, "Another render pass has already been started");
360-
VERIFY(!m_State.RenderingBegan, "Rendering has already begun");
360+
VERIFY(m_State.DynamicRenderingHash == 0, "Rendering has already begun");
361361
VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
362-
vkCmdBeginRenderingKHR(m_VkCmdBuffer, &RenderingInfo);
363-
m_State.RenderingBegan = true;
362+
363+
if (m_State.DynamicRenderingHash != Hash)
364+
{
365+
FlushBarriers();
366+
367+
vkCmdBeginRenderingKHR(m_VkCmdBuffer, &RenderingInfo);
368+
m_State.DynamicRenderingHash = Hash;
369+
}
364370
}
365371

366372
__forceinline void EndRendering()
367373
{
368374
VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
369-
VERIFY(m_State.RenderingBegan, "Rendering has not begun");
375+
VERIFY(m_State.DynamicRenderingHash != 0, "Rendering has not begun");
370376
vkCmdEndRenderingKHR(m_VkCmdBuffer);
371-
m_State.RenderingBegan = false;
377+
m_State.DynamicRenderingHash = 0;
372378
}
373379

374380
__forceinline void EndRenderScope()
375381
{
376382
if (m_State.RenderPass != VK_NULL_HANDLE)
377383
EndRenderPass();
378-
else if (m_State.RenderingBegan)
384+
else if (m_State.DynamicRenderingHash != 0)
379385
EndRendering();
380386
}
381387

@@ -803,22 +809,22 @@ class VulkanCommandBuffer
803809

804810
struct StateCache
805811
{
806-
VkRenderPass RenderPass = VK_NULL_HANDLE;
807-
VkFramebuffer Framebuffer = VK_NULL_HANDLE;
808-
VkPipeline GraphicsPipeline = VK_NULL_HANDLE;
809-
VkPipeline ComputePipeline = VK_NULL_HANDLE;
810-
VkPipeline RayTracingPipeline = VK_NULL_HANDLE;
811-
VkBuffer IndexBuffer = VK_NULL_HANDLE;
812-
VkDeviceSize IndexBufferOffset = 0;
813-
VkIndexType IndexType = VK_INDEX_TYPE_MAX_ENUM;
814-
uint32_t FramebufferWidth = 0;
815-
uint32_t FramebufferHeight = 0;
816-
uint32_t InsidePassQueries = 0;
817-
uint32_t OutsidePassQueries = 0;
818-
bool RenderingBegan = false;
812+
VkRenderPass RenderPass = VK_NULL_HANDLE;
813+
VkFramebuffer Framebuffer = VK_NULL_HANDLE;
814+
VkPipeline GraphicsPipeline = VK_NULL_HANDLE;
815+
VkPipeline ComputePipeline = VK_NULL_HANDLE;
816+
VkPipeline RayTracingPipeline = VK_NULL_HANDLE;
817+
VkBuffer IndexBuffer = VK_NULL_HANDLE;
818+
VkDeviceSize IndexBufferOffset = 0;
819+
VkIndexType IndexType = VK_INDEX_TYPE_MAX_ENUM;
820+
uint32_t FramebufferWidth = 0;
821+
uint32_t FramebufferHeight = 0;
822+
uint32_t InsidePassQueries = 0;
823+
uint32_t OutsidePassQueries = 0;
824+
size_t DynamicRenderingHash = 0;
819825
};
820826

821-
__forceinline bool IsInRenderScope() const { return m_State.RenderPass != VK_NULL_HANDLE || m_State.RenderingBegan; }
827+
__forceinline bool IsInRenderScope() const { return m_State.RenderPass != VK_NULL_HANDLE || m_State.DynamicRenderingHash != 0; }
822828

823829
const StateCache& GetState() const { return m_State; }
824830

0 commit comments

Comments
 (0)