1 /* 2 * Copyright (C) 2023 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/unique_ptr.h> 22 #include <base/containers/unordered_map.h> 23 #include <base/containers/vector.h> 24 #include <core/threading/intf_thread_pool.h> 25 #include <render/namespace.h> 26 27 #include "nodecontext/render_command_list.h" 28 #include "render_backend.h" 29 #include "vulkan/device_vk.h" 30 #include "vulkan/pipeline_create_functions_vk.h" 31 32 #if (RENDER_PERF_ENABLED == 1) 33 #include "device/gpu_buffer.h" 34 #include "perf/cpu_timer.h" 35 #include "perf/gpu_query_manager.h" 36 #endif 37 38 CORE_BEGIN_NAMESPACE() 39 class IThreadPool; 40 CORE_END_NAMESPACE() 41 RENDER_BEGIN_NAMESPACE() 42 class Device; 43 class DeviceVk; 44 class GpuResourceManager; 45 class NodeContextPsoManager; 46 class NodeContextPoolManager; 47 class RenderBarrierList; 48 class RenderCommandList; 49 struct LowLevelCommandBufferVk; 50 struct RenderCommandContext; 51 struct RenderPerfTimings; 52 53 struct NodeGraphBackBufferConfiguration; 54 55 class IRenderBackendNode; 56 57 struct CommandBufferSubmitter { 58 struct CommandBuffer { 59 VkCommandBuffer commandBuffer { VK_NULL_HANDLE }; 60 VkSemaphore semaphore { VK_NULL_HANDLE }; 61 }; 62 63 VkSemaphore presentationWaitSemaphore { VK_NULL_HANDLE }; 64 BASE_NS::vector<CommandBuffer> commandBuffers; 65 }; 66 67 #if (RENDER_PERF_ENABLED == 1) 68 struct PerfCounters { 69 uint32_t drawCount { 0u }; 70 uint32_t drawIndirectCount { 0u }; 71 uint32_t dispatchCount { 0u }; 72 uint32_t dispatchIndirectCount { 0u }; 73 74 uint32_t bindPipelineCount { 0u }; 75 uint32_t renderPassCount { 0u }; 76 77 uint32_t updateDescriptorSetCount { 0u }; 78 uint32_t bindDescriptorSetCount { 0u }; 79 80 uint32_t triangleCount { 0u }; 81 uint32_t instanceCount { 0u }; 82 }; 83 #endif 84 85 /** 86 RenderBackVk. 87 Vulkan render backend. 88 Gets a list of intermediate render command lists and creates a Vulkan command buffers in parallel. 89 Generally one render command list will generate one vulkan command buffer. 90 **/ 91 class RenderBackendVk final : public RenderBackend { 92 public: 93 RenderBackendVk(Device& dev, GpuResourceManager& gpuResourceManager, const CORE_NS::IParallelTaskQueue::Ptr& queue); 94 ~RenderBackendVk() = default; 95 96 void Render(RenderCommandFrameData& renderCommandFrameData, 97 const RenderBackendBackBufferConfiguration& backBufferConfig) override; 98 void Present(const RenderBackendBackBufferConfiguration& backBufferConfig) override; 99 100 private: 101 struct StateCache { 102 const RenderCommandBeginRenderPass* renderCommandBeginRenderPass { nullptr }; 103 LowLevelRenderPassDataVk lowLevelRenderPassData; 104 LowLevelPipelineLayoutDataVk lowLevelPipelineLayoutData; 105 106 IRenderBackendNode* backendNode { nullptr }; 107 108 // matching pso handle to pipeline layout 109 RenderHandle psoHandle; 110 VkPipelineLayout pipelineLayout { VK_NULL_HANDLE }; 111 112 // has bitmask for immutable samplers with special handling needed resources 113 // every descriptor set uses 16 bits (for max descriptor set bindings) 114 uint64_t pipelineDescSetHash { 0u }; 115 116 #if (RENDER_PERF_ENABLED == 1) 117 mutable PerfCounters perfCounters; 118 #endif 119 }; 120 121 struct MultiRenderCommandListDesc { 122 RenderCommandContext* baseContext { nullptr }; 123 124 uint32_t multiRenderCommandListIndex { 0 }; 125 uint32_t multiRenderCommandListCount { 0 }; 126 }; 127 128 struct DebugNames { 129 BASE_NS::string_view renderCommandListName; 130 BASE_NS::string_view renderCommandBufferName; // multi-renderpass has the first render command list name 131 }; 132 133 // called once in the beginning of rendering to acquire and setup possible swapchain 134 void AcquirePresentationInfo( 135 RenderCommandFrameData& renderCommandFrameData, const RenderBackendBackBufferConfiguration& backBufferConfig); 136 137 void RenderProcessCommandLists(RenderCommandFrameData& renderCommandFrameData); 138 void RenderProcessSubmitCommandLists( 139 RenderCommandFrameData& renderCommandFrameData, const RenderBackendBackBufferConfiguration& backBufferConfig); 140 void RenderSingleCommandList(RenderCommandContext& renderCommandCtx, const uint32_t cmdBufIdx, 141 const MultiRenderCommandListDesc& multiRenderCommandListDesc, const DebugNames& debugNames); 142 143 void RenderCommand(const RenderCommandDraw& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 144 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 145 void RenderCommand(const RenderCommandDrawIndirect& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 146 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 147 void RenderCommand(const RenderCommandDispatch& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 148 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 149 void RenderCommand(const RenderCommandDispatchIndirect& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 150 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 151 152 void RenderCommand(const RenderCommandBindPipeline& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 153 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, StateCache& stateCache); 154 void RenderCommand(const RenderCommandBindVertexBuffers& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 155 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 156 void RenderCommand(const RenderCommandBindIndexBuffer& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 157 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 158 159 void RenderCommand(const RenderCommandBeginRenderPass& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 160 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, StateCache& stateCache); 161 void RenderCommand(const RenderCommandNextSubpass& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 162 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 163 void RenderCommand(const RenderCommandEndRenderPass& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 164 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, StateCache& stateCache); 165 166 void RenderCommand(const RenderCommandCopyBuffer& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 167 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 168 void RenderCommand(const RenderCommandCopyBufferImage& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 169 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 170 void RenderCommand(const RenderCommandCopyImage& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 171 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 172 173 void RenderCommand(const RenderCommandBarrierPoint& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 174 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache, 175 const RenderBarrierList& rbl); 176 177 void RenderCommand(const RenderCommandBlitImage& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 178 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 179 180 void RenderCommand(const RenderCommandUpdateDescriptorSets& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 181 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache, 182 NodeContextDescriptorSetManager& ncdsm); 183 void RenderCommand(const RenderCommandBindDescriptorSets& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 184 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, StateCache& stateCache, 185 NodeContextDescriptorSetManager& ncdsm); 186 187 void RenderCommand(const RenderCommandPushConstant& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 188 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 189 190 void RenderCommand(const RenderCommandBuildAccelerationStructure& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 191 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 192 193 // dynamic states 194 void RenderCommand(const RenderCommandDynamicStateViewport& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 195 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 196 void RenderCommand(const RenderCommandDynamicStateScissor& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 197 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 198 void RenderCommand(const RenderCommandDynamicStateLineWidth& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 199 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 200 void RenderCommand(const RenderCommandDynamicStateDepthBias& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 201 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 202 void RenderCommand(const RenderCommandDynamicStateBlendConstants& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 203 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 204 void RenderCommand(const RenderCommandDynamicStateDepthBounds& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 205 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 206 void RenderCommand(const RenderCommandDynamicStateStencil& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 207 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 208 209 void RenderCommand(const RenderCommandExecuteBackendFramePosition& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 210 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 211 212 // queries 213 void RenderCommand(const RenderCommandWriteTimestamp& renderCmd, const LowLevelCommandBufferVk& cmdBuf, 214 NodeContextPsoManager& psoMgr, const NodeContextPoolManager& poolMgr, const StateCache& stateCache); 215 216 Device& device_; 217 DeviceVk& deviceVk_; 218 GpuResourceManager& gpuResourceMgr_; 219 CORE_NS::IParallelTaskQueue* queue_; 220 221 CommandBufferSubmitter commandBufferSubmitter_; 222 223 struct PresentationInfo { 224 bool useSwapchain { false }; 225 bool validAcquire { false }; 226 uint32_t swapchainImageIndex { ~0u }; 227 VkSemaphore swapchainSemaphore { VK_NULL_HANDLE }; 228 bool presentationLayoutChangeNeeded { false }; 229 uint32_t renderNodeCommandListIndex { ~0u }; 230 GpuResourceState renderGraphProcessedState; 231 ImageLayout imageLayout { ImageLayout::CORE_IMAGE_LAYOUT_UNDEFINED }; 232 VkImage swapchainImage { VK_NULL_HANDLE }; 233 }; 234 PresentationInfo presentationInfo_; 235 236 // internal presentationInfo_ state change (called 0 or 1 time from random thread for presentation layout change) 237 void RenderPresentationLayout(const LowLevelCommandBufferVk& cmdBuf); 238 239 #if (RENDER_PERF_ENABLED == 1) 240 241 void StartFrameTimers(RenderCommandFrameData& renderCommandFrameData); 242 void EndFrameTimers(); 243 244 void WritePerfTimeStamp(const LowLevelCommandBufferVk& cmdBuf, const BASE_NS::string_view name, 245 const uint32_t queryIndex, const VkPipelineStageFlagBits stageFlagBits); 246 void CopyPerfTimeStamp( 247 const LowLevelCommandBufferVk& cmdBuf, const BASE_NS::string_view name, const StateCache& cache); 248 249 BASE_NS::unique_ptr<GpuQueryManager> gpuQueryMgr_; 250 struct PerfDataSet { 251 EngineResourceHandle gpuHandle; 252 CpuTimer cpuTimer; 253 254 uint32_t gpuBufferOffset { 0 }; 255 }; 256 BASE_NS::unordered_map<BASE_NS::string, PerfDataSet> timers_; 257 #if (RENDER_GPU_TIMESTAMP_QUERIES_ENABLED == 1) 258 struct PerfGpuTimerData { 259 uint32_t fullByteSize { 0 }; 260 uint32_t frameByteSize { 0 }; 261 uint32_t currentOffset { 0 }; 262 BASE_NS::unique_ptr<GpuBuffer> gpuBuffer; 263 void* mappedData { nullptr }; 264 }; 265 PerfGpuTimerData perfGpuTimerData_; 266 #endif 267 struct CommonBackendCpuTimers { 268 CpuTimer full; 269 CpuTimer acquire; 270 CpuTimer execute; 271 CpuTimer submit; 272 CpuTimer present; 273 }; 274 CommonBackendCpuTimers commonCpuTimers_; 275 #endif 276 }; 277 RENDER_END_NAMESPACE() 278 279 #endif // VULKAN_RENDER_BACKEND_VK_H 280