1 /* 2 * Copyright (c) 2022 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 55 struct NodeGraphBackBufferConfiguration; 56 57 class IRenderBackendNode; 58 59 struct CommandBufferSubmitter { 60 struct CommandBuffer { 61 VkCommandBuffer commandBuffer { VK_NULL_HANDLE }; 62 VkSemaphore semaphore { VK_NULL_HANDLE }; 63 64 // not submitted, executed in primary command buffer 65 VkCommandBuffer secondaryCommandBuffer { VK_NULL_HANDLE }; 66 }; 67 68 VkSemaphore presentationWaitSemaphore { VK_NULL_HANDLE }; 69 BASE_NS::vector<CommandBuffer> commandBuffers; 70 }; 71 72 #if (RENDER_PERF_ENABLED == 1) 73 struct PerfCounters { 74 uint32_t drawCount { 0u }; 75 uint32_t drawIndirectCount { 0u }; 76 uint32_t dispatchCount { 0u }; 77 uint32_t dispatchIndirectCount { 0u }; 78 79 uint32_t bindPipelineCount { 0u }; 80 uint32_t renderPassCount { 0u }; 81 82 uint32_t updateDescriptorSetCount { 0u }; 83 uint32_t bindDescriptorSetCount { 0u }; 84 85 uint32_t triangleCount { 0u }; 86 uint32_t instanceCount { 0u }; 87 }; 88 #else 89 struct PerfCounters {}; 90 #endif 91 92 /** 93 RenderBackVk. 94 Vulkan render backend. 95 Gets a list of intermediate render command lists and creates a Vulkan command buffers in parallel. 96 Generally one render command list will generate one vulkan command buffer. 97 **/ 98 class RenderBackendVk final : public RenderBackend { 99 public: 100 RenderBackendVk(Device& dev, GpuResourceManager& gpuResourceManager, CORE_NS::ITaskQueue* queue); 101 ~RenderBackendVk() override = default; 102 103 void Render(RenderCommandFrameData& renderCommandFrameData, 104 const RenderBackendBackBufferConfiguration& backBufferConfig) override; 105 void Present(const RenderBackendBackBufferConfiguration& backBufferConfig) override; 106 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 private: 133 struct MultiRenderCommandListDesc { 134 RenderCommandContext* baseContext { nullptr }; 135 136 uint32_t multiRenderCommandListIndex { 0 }; 137 uint32_t multiRenderCommandListCount { 0 }; 138 bool secondaryCommandBuffer { false }; 139 bool multiRenderNodeCmdList { false }; 140 }; 141 142 struct DebugNames { 143 BASE_NS::string_view renderCommandListName; 144 BASE_NS::string_view renderCommandBufferName; // multi-renderpass has the first render command list name 145 }; 146 147 // called once in the beginning of rendering to acquire and setup possible swapchain 148 void AcquirePresentationInfo( 149 RenderCommandFrameData& renderCommandFrameData, const RenderBackendBackBufferConfiguration& backBufferConfig); 150 151 void UpdateGlobalDescriptorSets(); 152 153 void RenderProcessCommandLists( 154 RenderCommandFrameData& renderCommandFrameData, const RenderBackendBackBufferConfiguration& backBufferConfig); 155 void RenderProcessSubmitCommandLists( 156 RenderCommandFrameData& renderCommandFrameData, const RenderBackendBackBufferConfiguration& backBufferConfig); 157 void RenderSingleCommandList(RenderCommandContext& renderCommandCtx, uint32_t cmdBufIdx, 158 const MultiRenderCommandListDesc& mrclDesc, const DebugNames& debugNames); 159 160 void UpdateCommandListDescriptorSets( 161 const RenderCommandList& renderCommandList, StateCache& stateCache, NodeContextDescriptorSetManager& ncdsm); 162 163 // secondary command buffers related methods 164 void RenderPrimaryRenderPass(const RenderCommandFrameData& renderCommandFrameData, 165 RenderCommandContext& renderCommandCtx, uint32_t cmdBufIdx, 166 const MultiRenderCommandListDesc& multiRenderCommandListDesc, const DebugNames& debugNames); 167 static void RenderExecuteSecondaryCommandLists( 168 const LowLevelCommandBufferVk& cmdBuffer, const LowLevelCommandBufferVk& executeCmdBuffer); 169 static VkCommandBufferInheritanceInfo RenderGetCommandBufferInheritanceInfo( 170 const RenderCommandList& renderCommandList, NodeContextPoolManager& poolMgr); 171 172 static void RenderCommand(const RenderCommandDraw& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 173 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 174 void RenderCommand(const RenderCommandDrawIndirect& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 175 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 176 static void RenderCommand(const RenderCommandDispatch& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 177 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 178 void RenderCommand(const RenderCommandDispatchIndirect& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 179 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 180 181 static void RenderCommand(const RenderCommandBindPipeline& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 182 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, StateCache& stateCache); 183 void RenderCommand(const RenderCommandBindVertexBuffers& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 184 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 185 void RenderCommand(const RenderCommandBindIndexBuffer& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 186 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 187 188 static void RenderCommand(const RenderCommandBeginRenderPass& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 189 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, StateCache& stateCache); 190 static void RenderCommand(const RenderCommandNextSubpass& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 191 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 192 static void RenderCommand(const RenderCommandEndRenderPass& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 193 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, StateCache& stateCache); 194 195 void RenderCommand(const RenderCommandCopyBuffer& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 196 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 197 void RenderCommand(const RenderCommandCopyBufferImage& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 198 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 199 void RenderCommand(const RenderCommandCopyImage& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 200 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 201 202 void RenderCommand(const RenderCommandBarrierPoint& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 203 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache, 204 const RenderBarrierList& rbl); 205 206 void RenderCommand(const RenderCommandBlitImage& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 207 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 208 209 void RenderCommand(const RenderCommandBindDescriptorSets& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 210 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, StateCache& stateCache, 211 NodeContextDescriptorSetManager& ncdsm); 212 213 static void RenderCommand(const RenderCommandPushConstant& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 214 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 215 216 void RenderCommand(const RenderCommandBuildAccelerationStructure& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 217 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 218 void RenderCommand(const RenderCommandCopyAccelerationStructureInstances& renderCmd, 219 const LowLevelCommandBufferVk& cmdBuf, NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, 220 const StateCache& stateCache); 221 222 void RenderCommand(const RenderCommandClearColorImage& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 223 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 224 225 // dynamic states 226 static void RenderCommand(const RenderCommandDynamicStateViewport& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 227 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 228 static void RenderCommand(const RenderCommandDynamicStateScissor& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 229 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 230 static void RenderCommand(const RenderCommandDynamicStateLineWidth& renderCmd, 231 const LowLevelCommandBufferVk& cmdBuf, NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, 232 const StateCache& stateCache); 233 static void RenderCommand(const RenderCommandDynamicStateDepthBias& renderCmd, 234 const LowLevelCommandBufferVk& cmdBuf, NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, 235 const StateCache& stateCache); 236 static void RenderCommand(const RenderCommandDynamicStateBlendConstants& renderCmd, 237 const LowLevelCommandBufferVk& cmdBuf, NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, 238 const StateCache& stateCache); 239 static void RenderCommand(const RenderCommandDynamicStateDepthBounds& renderCmd, 240 const LowLevelCommandBufferVk& cmdBuf, NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, 241 const StateCache& stateCache); 242 static void RenderCommand(const RenderCommandDynamicStateStencil& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 243 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 244 void RenderCommand(const RenderCommandDynamicStateFragmentShadingRate& renderCmd, 245 const LowLevelCommandBufferVk& cmdBuf, NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, 246 const StateCache& stateCache); 247 248 void RenderCommand(const RenderCommandExecuteBackendFramePosition& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 249 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 250 251 // queries 252 static void RenderCommand(const RenderCommandWriteTimestamp& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 253 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 254 255 // markers 256 257 #if (RENDER_DEBUG_MARKERS_ENABLED == 1) || (RENDER_DEBUG_COMMAND_MARKERS_ENABLED == 1) 258 void BeginDebugMarker( 259 const LowLevelCommandBufferVk& cmdBuf, const BASE_NS::string_view name, const BASE_NS::Math::Vec4 color); 260 void EndDebugMarker(const LowLevelCommandBufferVk& cmdBuf); 261 #endif 262 #if (RENDER_DEBUG_MARKERS_ENABLED == 1) 263 void RenderCommand(const RenderCommandBeginDebugMarker& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 264 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 265 void RenderCommand(const RenderCommandEndDebugMarker& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 266 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 267 #endif 268 269 Device& device_; 270 DeviceVk& deviceVk_; 271 GpuResourceManager& gpuResourceMgr_; 272 CORE_NS::ITaskQueue* const queue_ { nullptr }; 273 274 CommandBufferSubmitter commandBufferSubmitter_; 275 276 struct PresentationInfo { 277 bool useSwapchain { false }; 278 bool validAcquire { false }; 279 uint32_t swapchainImageIndex { ~0u }; 280 VkSemaphore swapchainSemaphore { VK_NULL_HANDLE }; 281 bool presentationLayoutChangeNeeded { false }; 282 uint32_t renderNodeCommandListIndex { ~0u }; 283 GpuResourceState renderGraphProcessedState; 284 ImageLayout imageLayout { ImageLayout::CORE_IMAGE_LAYOUT_UNDEFINED }; 285 VkImage swapchainImage { VK_NULL_HANDLE }; 286 VkSwapchainKHR swapchain { VK_NULL_HANDLE }; 287 PerfCounters performanceCounters {}; 288 }; 289 struct PresentationData { 290 bool present { true }; 291 BASE_NS::vector<PresentationInfo> infos; 292 }; 293 PresentationData presentationData_; 294 295 // process backend commands for all positions 296 BASE_NS::vector<ProcessBackendCommand> processBackendCommands_; 297 298 // internal presentationInfo_ state change (called 0 or 1 time from random thread for presentation layout change) 299 void RenderPresentationLayout(const LowLevelCommandBufferVk& cmdBuf, uint32_t cmdBufferIdx); 300 301 #if (RENDER_PERF_ENABLED == 1) 302 303 void StartFrameTimers(RenderCommandFrameData& renderCommandFrameData); 304 void EndFrameTimers(); 305 306 void WritePerfTimeStamp(const LowLevelCommandBufferVk& cmdBuf, const BASE_NS::string_view name, 307 const uint32_t queryIndex, const VkPipelineStageFlagBits stageFlagBits, const StateCache& stateCache); 308 void CopyPerfTimeStamp( 309 const LowLevelCommandBufferVk& cmdBuf, const BASE_NS::string_view name, const StateCache& stateCache); 310 311 BASE_NS::unique_ptr<GpuQueryManager> gpuQueryMgr_; 312 struct PerfDataSet { 313 EngineResourceHandle gpuHandle; 314 CpuTimer cpuTimer; 315 316 uint32_t gpuBufferOffset { 0 }; 317 318 PerfCounters perfCounters; 319 }; 320 BASE_NS::unordered_map<BASE_NS::string, PerfDataSet> timers_; 321 #if (RENDER_GPU_TIMESTAMP_QUERIES_ENABLED == 1) 322 struct PerfGpuTimerData { 323 uint32_t fullByteSize { 0 }; 324 uint32_t frameByteSize { 0 }; 325 uint32_t currentOffset { 0 }; 326 BASE_NS::unique_ptr<GpuBuffer> gpuBuffer; 327 void* mappedData { nullptr }; 328 329 std::atomic_int64_t fullGpuCounter = 0; 330 }; 331 PerfGpuTimerData perfGpuTimerData_; 332 #endif 333 struct CommonBackendCpuTimers { 334 CpuTimer full; 335 CpuTimer acquire; 336 CpuTimer execute; 337 CpuTimer submit; 338 CpuTimer present; 339 }; 340 CommonBackendCpuTimers commonCpuTimers_; 341 #endif 342 }; 343 RENDER_END_NAMESPACE() 344 345 #endif // VULKAN_RENDER_BACKEND_VK_H 346