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