Skip to content

Commit

Permalink
DeviceContextVk: initial implementation of dynamic rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
TheMostDiligent committed Feb 2, 2025
1 parent 59db520 commit 477edd8
Show file tree
Hide file tree
Showing 8 changed files with 323 additions and 42 deletions.
2 changes: 2 additions & 0 deletions Graphics/GraphicsEngineVulkan/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ set(INCLUDE
)

set(VULKAN_UTILS_INCLUDE
include/VulkanUtilities/RenderingInfoWrapper.hpp
include/VulkanUtilities/VulkanCommandBuffer.hpp
include/VulkanUtilities/VulkanCommandBufferPool.hpp
include/VulkanUtilities/VulkanDebug.hpp
Expand Down Expand Up @@ -128,6 +129,7 @@ set(SRC
)

set(VULKAN_UTILS_SRC
src/VulkanUtilities/RenderingInfoWrapper.cpp
src/VulkanUtilities/VulkanCommandBuffer.cpp
src/VulkanUtilities/VulkanCommandBufferPool.cpp
src/VulkanUtilities/VulkanDebug.cpp
Expand Down
11 changes: 8 additions & 3 deletions Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2024 Diligent Graphics LLC
* Copyright 2019-2025 Diligent Graphics LLC
* Copyright 2015-2019 Egor Yusov
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -52,6 +52,7 @@
#include "VulkanUtilities/VulkanCommandBufferPool.hpp"
#include "VulkanUtilities/VulkanCommandBuffer.hpp"
#include "VulkanUtilities/VulkanSyncObjectManager.hpp"
#include "VulkanUtilities/RenderingInfoWrapper.hpp"
#include "VulkanUploadHeap.hpp"
#include "VulkanDynamicHeap.hpp"
#include "ResourceReleaseQueue.hpp"
Expand Down Expand Up @@ -449,7 +450,7 @@ class DeviceContextVkImpl final : public DeviceContextNextGenBase<EngineVkImplTr
m_State.NumCommands = m_State.NumCommands != 0 ? m_State.NumCommands : 1;
if (m_CommandBuffer.GetVkCmdBuffer() == VK_NULL_HANDLE)
{
auto vkCmdBuff = m_CmdPool->GetCommandBuffer();
VkCommandBuffer vkCmdBuff = m_CmdPool->GetCommandBuffer();
m_CommandBuffer.SetVkCmdBuffer(vkCmdBuff, m_CmdPool->GetSupportedStagesMask(), m_CmdPool->GetSupportedAccessMask());
}
}
Expand Down Expand Up @@ -489,6 +490,7 @@ class DeviceContextVkImpl final : public DeviceContextNextGenBase<EngineVkImplTr

void ChooseRenderPassAndFramebuffer();

private:
VulkanUtilities::VulkanCommandBuffer m_CommandBuffer;

struct ContextState
Expand Down Expand Up @@ -558,7 +560,7 @@ class DeviceContextVkImpl final : public DeviceContextNextGenBase<EngineVkImplTr
std::vector<Uint32> m_DynamicBufferOffsets;

/// Temporary array used by CommitDescriptorSets
std::array<VkDescriptorSet, MAX_RESOURCE_SIGNATURES* MAX_DESCR_SET_PER_SIGNATURE> m_DescriptorSets = {};
std::array<VkDescriptorSet, (MAX_RESOURCE_SIGNATURES * MAX_DESCR_SET_PER_SIGNATURE)> m_DescriptorSets = {};

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

/// Dynamic rendering info.
std::unique_ptr<VulkanUtilities::RenderingInfoWrapper> m_DynamicRenderingInfo;

FixedBlockMemoryAllocator m_CmdListAllocator;

// Semaphores are not owned by the command context
Expand Down
14 changes: 12 additions & 2 deletions Graphics/GraphicsEngineVulkan/include/FramebufferCache.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2024 Diligent Graphics LLC
* Copyright 2019-2025 Diligent Graphics LLC
* Copyright 2015-2019 Egor Yusov
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -32,8 +32,10 @@

#include <unordered_map>
#include <mutex>
#include <memory>

#include "VulkanUtilities/VulkanObjectWrappers.hpp"
#include "VulkanUtilities/RenderingInfoWrapper.hpp"

namespace Diligent
{
Expand Down Expand Up @@ -77,7 +79,15 @@ class FramebufferCache
void OnDestroyImageView(VkImageView ImgView);
void OnDestroyRenderPass(VkRenderPass Pass);

private:
static std::unique_ptr<VulkanUtilities::RenderingInfoWrapper> CreateDyanmicRenderInfo(
const FramebufferCacheKey& Key,
bool UseDepthAttachment,
bool UseStencilAttachment,
uint32_t width,
uint32_t height,
uint32_t layers,
uint32_t viewMask);

RenderDeviceVkImpl& m_DeviceVk;

struct FramebufferCacheKeyHash
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* Copyright 2025 Diligent Graphics LLC
*
* 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

#include <memory>

#include "VulkanHeaders.h"
#include "DebugUtilities.hpp"

namespace VulkanUtilities
{

class RenderingInfoWrapper
{
public:
RenderingInfoWrapper(size_t Hash,
uint32_t ColorAttachmentCount,
bool UseDepthAttachment,
bool UseStencilAttachment);

// clang-format off
RenderingInfoWrapper (const RenderingInfoWrapper&) = delete;
RenderingInfoWrapper (RenderingInfoWrapper&&) = delete;
RenderingInfoWrapper& operator=(const RenderingInfoWrapper&) = delete;
RenderingInfoWrapper& operator=(RenderingInfoWrapper&&) = delete;
// clang-format on

operator const VkRenderingInfoKHR&() const { return m_RI; }

size_t GetHash() const { return m_Hash; }

RenderingInfoWrapper& SetFlags(VkRenderingFlagsKHR flags)
{
m_RI.flags = flags;
return *this;
}

RenderingInfoWrapper& SetRenderArea(const VkRect2D& renderArea)
{
m_RI.renderArea = renderArea;
return *this;
}

RenderingInfoWrapper& SetLayerCount(uint32_t layerCount)
{
m_RI.layerCount = layerCount;
return *this;
}

RenderingInfoWrapper& SetViewMask(uint32_t viewMask)
{
m_RI.viewMask = viewMask;
return *this;
}

VkRenderingAttachmentInfoKHR& GetColorAttachment(uint32_t Index)
{
VERIFY_EXPR(Index < m_RI.colorAttachmentCount);
return m_Attachments[Index];
}

VkRenderingAttachmentInfoKHR& GetDepthAttachment()
{
VERIFY_EXPR(m_RI.pDepthAttachment != nullptr && m_DepthAttachmentIndex != ~0u);
return m_Attachments[m_DepthAttachmentIndex];
}

VkRenderingAttachmentInfoKHR& GetStencilAttachment()
{
VERIFY_EXPR(m_RI.pStencilAttachment != nullptr && m_StencilAttachmentIndex != ~0u);
return m_Attachments[m_StencilAttachmentIndex];
}

private:
VkRenderingInfoKHR m_RI;

const size_t m_Hash = 0;

std::unique_ptr<VkRenderingAttachmentInfoKHR[]> m_Attachments;

uint32_t m_DepthAttachmentIndex = ~0u;
uint32_t m_StencilAttachmentIndex = ~0u;
};

} // namespace VulkanUtilities
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ class VulkanCommandBuffer
{
VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
VERIFY(m_State.RenderPass == VK_NULL_HANDLE, "Current pass has not been ended");
VERIFY(!m_State.RenderingBegan, "Current dynamic render pass has not been ended");
VERIFY(m_State.DynamicRenderingHash == 0, "Current dynamic render pass has not been ended");

if (m_State.RenderPass != RenderPass || m_State.Framebuffer != Framebuffer)
{
Expand Down Expand Up @@ -354,28 +354,34 @@ class VulkanCommandBuffer
vkCmdNextSubpass(m_VkCmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
}

__forceinline void BeginRendering(const VkRenderingInfoKHR& RenderingInfo)
__forceinline void BeginRendering(const VkRenderingInfoKHR& RenderingInfo, size_t Hash)
{
VERIFY(m_State.RenderPass == VK_NULL_HANDLE, "Another render pass has already been started");
VERIFY(!m_State.RenderingBegan, "Rendering has already begun");
VERIFY(m_State.DynamicRenderingHash == 0, "Rendering has already begun");
VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
vkCmdBeginRenderingKHR(m_VkCmdBuffer, &RenderingInfo);
m_State.RenderingBegan = true;

if (m_State.DynamicRenderingHash != Hash)
{
FlushBarriers();

vkCmdBeginRenderingKHR(m_VkCmdBuffer, &RenderingInfo);
m_State.DynamicRenderingHash = Hash;
}
}

__forceinline void EndRendering()
{
VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
VERIFY(m_State.RenderingBegan, "Rendering has not begun");
VERIFY(m_State.DynamicRenderingHash != 0, "Rendering has not begun");
vkCmdEndRenderingKHR(m_VkCmdBuffer);
m_State.RenderingBegan = false;
m_State.DynamicRenderingHash = 0;
}

__forceinline void EndRenderScope()
{
if (m_State.RenderPass != VK_NULL_HANDLE)
EndRenderPass();
else if (m_State.RenderingBegan)
else if (m_State.DynamicRenderingHash != 0)
EndRendering();
}

Expand Down Expand Up @@ -803,22 +809,22 @@ class VulkanCommandBuffer

struct StateCache
{
VkRenderPass RenderPass = VK_NULL_HANDLE;
VkFramebuffer Framebuffer = VK_NULL_HANDLE;
VkPipeline GraphicsPipeline = VK_NULL_HANDLE;
VkPipeline ComputePipeline = VK_NULL_HANDLE;
VkPipeline RayTracingPipeline = VK_NULL_HANDLE;
VkBuffer IndexBuffer = VK_NULL_HANDLE;
VkDeviceSize IndexBufferOffset = 0;
VkIndexType IndexType = VK_INDEX_TYPE_MAX_ENUM;
uint32_t FramebufferWidth = 0;
uint32_t FramebufferHeight = 0;
uint32_t InsidePassQueries = 0;
uint32_t OutsidePassQueries = 0;
bool RenderingBegan = false;
VkRenderPass RenderPass = VK_NULL_HANDLE;
VkFramebuffer Framebuffer = VK_NULL_HANDLE;
VkPipeline GraphicsPipeline = VK_NULL_HANDLE;
VkPipeline ComputePipeline = VK_NULL_HANDLE;
VkPipeline RayTracingPipeline = VK_NULL_HANDLE;
VkBuffer IndexBuffer = VK_NULL_HANDLE;
VkDeviceSize IndexBufferOffset = 0;
VkIndexType IndexType = VK_INDEX_TYPE_MAX_ENUM;
uint32_t FramebufferWidth = 0;
uint32_t FramebufferHeight = 0;
uint32_t InsidePassQueries = 0;
uint32_t OutsidePassQueries = 0;
size_t DynamicRenderingHash = 0;
};

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

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

Expand Down
Loading

0 comments on commit 477edd8

Please sign in to comment.