1 /* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef VULKAN_RENDER_BACKEND_VK_H 17 #define VULKAN_RENDER_BACKEND_VK_H 18 19 #include <vulkan/vulkan_core.h> 20 21 #include <base/containers/array_view.h> 22 #include <base/containers/unique_ptr.h> 23 #include <base/containers/unordered_map.h> 24 #include <base/containers/vector.h> 25 #include <core/threading/intf_thread_pool.h> 26 #include <render/namespace.h> 27 28 #include "nodecontext/render_command_list.h" 29 #include "render_backend.h" 30 #include "vulkan/device_vk.h" 31 #include "vulkan/pipeline_create_functions_vk.h" 32 33 #if (RENDER_PERF_ENABLED == 1) 34 #include <atomic> 35 36 #include "device/gpu_buffer.h" 37 #include "perf/cpu_timer.h" 38 #include "perf/gpu_query_manager.h" 39 #endif 40 41 CORE_BEGIN_NAMESPACE() 42 class IThreadPool; 43 CORE_END_NAMESPACE() 44 RENDER_BEGIN_NAMESPACE() 45 class Device; 46 class DeviceVk; 47 class GpuResourceManager; 48 class NodeContextPsoManager; 49 class NodeContextPoolManager; 50 class RenderBarrierList; 51 class RenderCommandList; 52 struct LowLevelCommandBufferVk; 53 struct RenderCommandContext; 54 struct RenderPerfTimings; 55 56 struct NodeGraphBackBufferConfiguration; 57 58 class IRenderBackendNode; 59 60 struct CommandBufferSubmitter { 61 struct CommandBuffer { 62 VkCommandBuffer commandBuffer { VK_NULL_HANDLE }; 63 VkSemaphore semaphore { VK_NULL_HANDLE }; 64 65 // not submitted, executed in primary command buffer 66 VkCommandBuffer secondaryCommandBuffer { VK_NULL_HANDLE }; 67 }; 68 69 VkSemaphore presentationWaitSemaphore { VK_NULL_HANDLE }; 70 BASE_NS::vector<CommandBuffer> commandBuffers; 71 }; 72 73 #if (RENDER_PERF_ENABLED == 1) 74 struct PerfCounters { 75 uint32_t drawCount { 0u }; 76 uint32_t drawIndirectCount { 0u }; 77 uint32_t dispatchCount { 0u }; 78 uint32_t dispatchIndirectCount { 0u }; 79 80 uint32_t bindPipelineCount { 0u }; 81 uint32_t renderPassCount { 0u }; 82 83 uint32_t updateDescriptorSetCount { 0u }; 84 uint32_t bindDescriptorSetCount { 0u }; 85 86 uint32_t triangleCount { 0u }; 87 uint32_t instanceCount { 0u }; 88 }; 89 #endif 90 91 /** 92 RenderBackVk. 93 Vulkan render backend. 94 Gets a list of intermediate render command lists and creates a Vulkan command buffers in parallel. 95 Generally one render command list will generate one vulkan command buffer. 96 **/ 97 class RenderBackendVk final : public RenderBackend { 98 public: 99 RenderBackendVk(Device& dev, GpuResourceManager& gpuResourceManager, const CORE_NS::IParallelTaskQueue::Ptr& queue); 100 ~RenderBackendVk() = default; 101 102 void Render(RenderCommandFrameData& renderCommandFrameData, 103 const RenderBackendBackBufferConfiguration& backBufferConfig) override; 104 void Present(const RenderBackendBackBufferConfiguration& backBufferConfig) override; 105 106 private: 107 struct StateCache { 108 const RenderCommandBeginRenderPass* renderCommandBeginRenderPass { nullptr }; 109 LowLevelRenderPassDataVk lowLevelRenderPassData; 110 LowLevelPipelineLayoutDataVk lowLevelPipelineLayoutData; 111 bool primaryRenderPass { false }; // related to secondary command buffers 112 bool secondaryCommandBuffer { false }; // related to secondary command buffers 113 bool validCommandList { true }; 114 bool validBindings { true }; 115 116 IRenderBackendNode* backendNode { nullptr }; 117 118 // matching pso handle to pipeline layout 119 RenderHandle psoHandle; 120 VkPipeline pipeline { VK_NULL_HANDLE }; 121 VkPipelineLayout pipelineLayout { VK_NULL_HANDLE }; 122 123 // has bitmask for immutable samplers with special handling needed resources 124 // every descriptor set uses 16 bits (for max descriptor set bindings) 125 uint64_t pipelineDescSetHash { 0u }; 126 127 #if (RENDER_PERF_ENABLED == 1) 128 mutable PerfCounters perfCounters; 129 #endif 130 }; 131 132 struct MultiRenderCommandListDesc { 133 RenderCommandContext* baseContext { nullptr }; 134 135 uint32_t multiRenderCommandListIndex { 0 }; 136 uint32_t multiRenderCommandListCount { 0 }; 137 bool secondaryCommandBuffer { false }; 138 bool multiRenderNodeCmdList { false }; 139 }; 140 141 struct DebugNames { 142 BASE_NS::string_view renderCommandListName; 143 BASE_NS::string_view renderCommandBufferName; // multi-renderpass has the first render command list name 144 }; 145 146 // called once in the beginning of rendering to acquire and setup possible swapchain 147 void AcquirePresentationInfo( 148 RenderCommandFrameData& renderCommandFrameData, const RenderBackendBackBufferConfiguration& backBufferConfig); 149 150 void RenderProcessCommandLists( 151 RenderCommandFrameData& renderCommandFrameData, const RenderBackendBackBufferConfiguration& backBufferConfig); 152 void RenderProcessSubmitCommandLists( 153 RenderCommandFrameData& renderCommandFrameData, const RenderBackendBackBufferConfiguration& backBufferConfig); 154 void RenderSingleCommandList(RenderCommandContext& renderCommandCtx, const uint32_t cmdBufIdx, 155 const MultiRenderCommandListDesc& mrclDesc, const DebugNames& debugNames); 156 157 void UpdateCommandListDescriptorSets( 158 const RenderCommandList& renderCommandList, StateCache& stateCache, NodeContextDescriptorSetManager& ncdsm); 159 160 // secondary command buffers related methods 161 void RenderPrimaryRenderPass(const RenderCommandFrameData& renderCommandFrameData, 162 RenderCommandContext& renderCommandCtx, const uint32_t cmdBufIdx, 163 const MultiRenderCommandListDesc& multiRenderCommandListDesc, const DebugNames& debugNames); 164 void RenderExecuteSecondaryCommandLists( 165 const LowLevelCommandBufferVk& cmdBuffer, const LowLevelCommandBufferVk& executeCmdBuffer); 166 VkCommandBufferInheritanceInfo RenderGetCommandBufferInheritanceInfo( 167 const RenderCommandList& renderCommandList, NodeContextPoolManager& poolMgr); 168 169 void RenderCommand(const RenderCommandDraw& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 170 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 171 void RenderCommand(const RenderCommandDrawIndirect& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 172 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 173 void RenderCommand(const RenderCommandDispatch& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 174 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 175 void RenderCommand(const RenderCommandDispatchIndirect& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 176 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 177 178 void RenderCommand(const RenderCommandBindPipeline& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 179 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, StateCache& stateCache); 180 void RenderCommand(const RenderCommandBindVertexBuffers& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 181 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 182 void RenderCommand(const RenderCommandBindIndexBuffer& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 183 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 184 185 void RenderCommand(const RenderCommandBeginRenderPass& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 186 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, StateCache& stateCache); 187 void RenderCommand(const RenderCommandNextSubpass& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 188 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 189 void RenderCommand(const RenderCommandEndRenderPass& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 190 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, StateCache& stateCache); 191 192 void RenderCommand(const RenderCommandCopyBuffer& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 193 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 194 void RenderCommand(const RenderCommandCopyBufferImage& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 195 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 196 void RenderCommand(const RenderCommandCopyImage& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 197 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 198 199 void RenderCommand(const RenderCommandBarrierPoint& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 200 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache, 201 const RenderBarrierList& rbl); 202 203 void RenderCommand(const RenderCommandBlitImage& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 204 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 205 206 void RenderCommand(const RenderCommandBindDescriptorSets& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 207 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, StateCache& stateCache, 208 NodeContextDescriptorSetManager& ncdsm); 209 210 void RenderCommand(const RenderCommandPushConstant& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 211 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 212 213 void RenderCommand(const RenderCommandBuildAccelerationStructure& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 214 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 215 216 void RenderCommand(const RenderCommandClearColorImage& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 217 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 218 219 // dynamic states 220 void RenderCommand(const RenderCommandDynamicStateViewport& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 221 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 222 void RenderCommand(const RenderCommandDynamicStateScissor& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 223 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 224 void RenderCommand(const RenderCommandDynamicStateLineWidth& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 225 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 226 void RenderCommand(const RenderCommandDynamicStateDepthBias& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 227 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 228 void RenderCommand(const RenderCommandDynamicStateBlendConstants& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 229 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 230 void RenderCommand(const RenderCommandDynamicStateDepthBounds& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 231 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 232 void RenderCommand(const RenderCommandDynamicStateStencil& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 233 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 234 void RenderCommand(const RenderCommandDynamicStateFragmentShadingRate& renderCmd, 235 const LowLevelCommandBufferVk& cmdBuf, NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, 236 const StateCache& stateCache); 237 238 void RenderCommand(const RenderCommandExecuteBackendFramePosition& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 239 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 240 241 // queries 242 void RenderCommand(const RenderCommandWriteTimestamp& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 243 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 244 245 Device& device_; 246 DeviceVk& deviceVk_; 247 GpuResourceManager& gpuResourceMgr_; 248 CORE_NS::IParallelTaskQueue* queue_ { nullptr }; 249 250 CommandBufferSubmitter commandBufferSubmitter_; 251 252 struct PresentationInfo { 253 bool useSwapchain { false }; 254 bool validAcquire { false }; 255 uint32_t swapchainImageIndex { ~0u }; 256 VkSemaphore swapchainSemaphore { VK_NULL_HANDLE }; 257 bool presentationLayoutChangeNeeded { false }; 258 uint32_t renderNodeCommandListIndex { ~0u }; 259 GpuResourceState renderGraphProcessedState; 260 ImageLayout imageLayout { ImageLayout::CORE_IMAGE_LAYOUT_UNDEFINED }; 261 VkImage swapchainImage { VK_NULL_HANDLE }; 262 VkSwapchainKHR swapchain { VK_NULL_HANDLE }; 263 }; 264 struct PresentationData { 265 bool present { true }; 266 BASE_NS::vector<PresentationInfo> infos; 267 }; 268 PresentationData presentationData_; 269 270 // internal presentationInfo_ state change (called 0 or 1 time from random thread for presentation layout change) 271 void RenderPresentationLayout(const LowLevelCommandBufferVk& cmdBuf, const uint32_t cmdBufferIdx); 272 273 #if (RENDER_PERF_ENABLED == 1) 274 275 void StartFrameTimers(RenderCommandFrameData& renderCommandFrameData); 276 void EndFrameTimers(); 277 278 void WritePerfTimeStamp(const LowLevelCommandBufferVk& cmdBuf, const BASE_NS::string_view name, 279 const uint32_t queryIndex, const VkPipelineStageFlagBits stageFlagBits, const StateCache& stateCache); 280 void CopyPerfTimeStamp( 281 const LowLevelCommandBufferVk& cmdBuf, const BASE_NS::string_view name, const StateCache& stateCache); 282 283 BASE_NS::unique_ptr<GpuQueryManager> gpuQueryMgr_; 284 struct PerfDataSet { 285 EngineResourceHandle gpuHandle; 286 CpuTimer cpuTimer; 287 288 uint32_t gpuBufferOffset { 0 }; 289 290 PerfCounters perfCounters; 291 }; 292 BASE_NS::unordered_map<BASE_NS::string, PerfDataSet> timers_; 293 #if (RENDER_GPU_TIMESTAMP_QUERIES_ENABLED == 1) 294 struct PerfGpuTimerData { 295 uint32_t fullByteSize { 0 }; 296 uint32_t frameByteSize { 0 }; 297 uint32_t currentOffset { 0 }; 298 BASE_NS::unique_ptr<GpuBuffer> gpuBuffer; 299 void* mappedData { nullptr }; 300 301 std::atomic_int64_t fullGpuCounter = 0; 302 }; 303 PerfGpuTimerData perfGpuTimerData_; 304 #endif 305 struct CommonBackendCpuTimers { 306 CpuTimer full; 307 CpuTimer acquire; 308 CpuTimer execute; 309 CpuTimer submit; 310 CpuTimer present; 311 }; 312 CommonBackendCpuTimers commonCpuTimers_; 313 #endif 314 }; 315 RENDER_END_NAMESPACE() 316 317 #endif // VULKAN_RENDER_BACKEND_VK_H 318