xref: /aosp_15_r20/external/skia/src/gpu/ganesh/vk/GrVkCommandBuffer.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7 
8 #ifndef GrVkCommandBuffer_DEFINED
9 #define GrVkCommandBuffer_DEFINED
10 
11 #include "include/core/SkRefCnt.h"
12 #include "include/private/base/SkAssert.h"
13 #include "include/private/base/SkTArray.h"
14 #include "include/private/base/SkTo.h"
15 #include "include/private/gpu/vk/SkiaVulkan.h"
16 #include "src/gpu/GpuRefCnt.h"
17 #include "src/gpu/RefCntedCallback.h"
18 #include "src/gpu/ganesh/GrBuffer.h"
19 #include "src/gpu/ganesh/GrManagedResource.h"
20 #include "src/gpu/ganesh/GrSurface.h"
21 #include "src/gpu/ganesh/vk/GrVkSemaphore.h"
22 
23 #include <cstdint>
24 #include <memory>
25 #include <utility>
26 
27 class GrGpu;
28 class GrGpuBuffer;
29 class GrVkBuffer;
30 class GrVkCommandPool;
31 class GrVkFramebuffer;
32 class GrVkGpu;
33 class GrVkImage;
34 class GrVkPipeline;
35 class GrVkRenderPass;
36 struct GrSubmitInfo;
37 struct SkIRect;
38 
39 class GrVkCommandBuffer {
40 public:
~GrVkCommandBuffer()41     virtual ~GrVkCommandBuffer() {}
42 
43     void invalidateState();
44 
45     ////////////////////////////////////////////////////////////////////////////
46     // CommandBuffer commands
47     ////////////////////////////////////////////////////////////////////////////
48     enum BarrierType {
49         kBufferMemory_BarrierType,
50         kImageMemory_BarrierType
51     };
52 
53     void pipelineBarrier(const GrVkGpu* gpu,
54                          const GrManagedResource* resource,
55                          VkPipelineStageFlags srcStageMask,
56                          VkPipelineStageFlags dstStageMask,
57                          bool byRegion,
58                          BarrierType barrierType,
59                          void* barrier);
60 
61     void bindInputBuffer(GrVkGpu* gpu, uint32_t binding, sk_sp<const GrBuffer> buffer);
62 
63     void bindIndexBuffer(GrVkGpu* gpu, sk_sp<const GrBuffer> buffer);
64 
65     void bindPipeline(const GrVkGpu* gpu, sk_sp<const GrVkPipeline> pipeline);
66 
67     void bindDescriptorSets(const GrVkGpu* gpu,
68                             VkPipelineLayout layout,
69                             uint32_t firstSet,
70                             uint32_t setCount,
71                             const VkDescriptorSet* descriptorSets,
72                             uint32_t dynamicOffsetCount,
73                             const uint32_t* dynamicOffsets);
74 
75     void pushConstants(const GrVkGpu* gpu, VkPipelineLayout layout,
76                        VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size,
77                        const void* values);
78 
79     void setViewport(const GrVkGpu* gpu,
80                      uint32_t firstViewport,
81                      uint32_t viewportCount,
82                      const VkViewport* viewports);
83 
84     void setScissor(const GrVkGpu* gpu,
85                     uint32_t firstScissor,
86                     uint32_t scissorCount,
87                     const VkRect2D* scissors);
88 
89     void setBlendConstants(const GrVkGpu* gpu, const float blendConstants[4]);
90 
91     // Commands that only work inside of a render pass
92     void clearAttachments(const GrVkGpu* gpu,
93                           int numAttachments,
94                           const VkClearAttachment* attachments,
95                           int numRects,
96                           const VkClearRect* clearRects);
97 
98     void drawIndexed(const GrVkGpu* gpu,
99                      uint32_t indexCount,
100                      uint32_t instanceCount,
101                      uint32_t firstIndex,
102                      int32_t vertexOffset,
103                      uint32_t firstInstance);
104 
105     void draw(const GrVkGpu* gpu,
106               uint32_t vertexCount,
107               uint32_t instanceCount,
108               uint32_t firstVertex,
109               uint32_t firstInstance);
110 
111     void drawIndirect(const GrVkGpu* gpu,
112                       sk_sp<const GrBuffer> indirectBuffer,
113                       VkDeviceSize offset,
114                       uint32_t drawCount,
115                       uint32_t stride);
116 
117     void drawIndexedIndirect(const GrVkGpu* gpu,
118                              sk_sp<const GrBuffer> indirectBuffer,
119                              VkDeviceSize offset,
120                              uint32_t drawCount,
121                              uint32_t stride);
122 
123     // Add ref-counted resource that will be tracked and released when this command buffer finishes
124     // execution
addResource(sk_sp<const GrManagedResource> resource)125     void addResource(sk_sp<const GrManagedResource> resource) {
126         SkASSERT(resource);
127         fTrackedResources.push_back(std::move(resource));
128     }
addResource(const GrManagedResource * resource)129     void addResource(const GrManagedResource* resource) {
130         this->addResource(sk_ref_sp(resource));
131     }
132 
133     // Add ref-counted resource that will be tracked and released when this command buffer finishes
134     // execution. When it is released, it will signal that the resource can be recycled for reuse.
addRecycledResource(gr_rp<const GrRecycledResource> resource)135     void addRecycledResource(gr_rp<const GrRecycledResource> resource) {
136         SkASSERT(resource);
137         fTrackedRecycledResources.push_back(std::move(resource));
138     }
139 
addRecycledResource(const GrRecycledResource * resource)140     void addRecycledResource(const GrRecycledResource* resource) {
141         this->addRecycledResource(gr_ref_rp<const GrRecycledResource>(resource));
142     }
143 
addGrBuffer(sk_sp<const GrBuffer> buffer)144     void addGrBuffer(sk_sp<const GrBuffer> buffer) {
145         fTrackedGpuBuffers.push_back(std::move(buffer));
146     }
147 
addGrSurface(sk_sp<const GrSurface> surface)148     void addGrSurface(sk_sp<const GrSurface> surface) {
149         fTrackedGpuSurfaces.push_back(std::move(surface));
150     }
151 
152     void releaseResources();
153 
154     void freeGPUData(const GrGpu* gpu, VkCommandPool pool) const;
155 
hasWork()156     bool hasWork() const { return fHasWork; }
157 
158 protected:
159     GrVkCommandBuffer(VkCommandBuffer cmdBuffer, bool isWrapped = false)
fIsActive(isWrapped)160             : fIsActive(isWrapped) // All wrapped command buffers start as active
161             , fCmdBuffer(cmdBuffer)
162             , fIsWrapped(isWrapped) {
163         this->invalidateState();
164     }
165 
isWrapped()166     bool isWrapped() const { return fIsWrapped; }
167 
168     void addingWork(const GrVkGpu* gpu);
169 
170     void submitPipelineBarriers(const GrVkGpu* gpu, bool forSelfDependency = false);
171 
172 private:
173     static constexpr int kInitialTrackedResourcesCount = 32;
174 
175 protected:
176     template <typename T>
177     using TrackedResourceArray = skia_private::STArray<kInitialTrackedResourcesCount, T>;
178     TrackedResourceArray<sk_sp<const GrManagedResource>> fTrackedResources;
179     TrackedResourceArray<gr_rp<const GrRecycledResource>> fTrackedRecycledResources;
180     skia_private::STArray<16, sk_sp<const GrBuffer>> fTrackedGpuBuffers;
181     skia_private::STArray<16, gr_cb<const GrSurface>> fTrackedGpuSurfaces;
182 
183     // Tracks whether we are in the middle of a command buffer begin/end calls and thus can add
184     // new commands to the buffer;
185     bool                      fIsActive;
186     bool                      fHasWork = false;
187 
188     // Stores a pointer to the current active render pass (i.e. begin has been called but not
189     // end). A nullptr means there is no active render pass. The GrVKCommandBuffer does not own
190     // the render pass.
191     const GrVkRenderPass*     fActiveRenderPass = nullptr;
192 
193     VkCommandBuffer           fCmdBuffer;
194 
onReleaseResources()195     virtual void onReleaseResources() {}
196     virtual void onFreeGPUData(const GrVkGpu* gpu) const = 0;
197 
198     static constexpr uint32_t kMaxInputBuffers = 2;
199 
200     VkBuffer fBoundInputBuffers[kMaxInputBuffers];
201     VkBuffer fBoundIndexBuffer;
202 
203     // Cached values used for dynamic state updates
204     VkViewport fCachedViewport;
205     VkRect2D   fCachedScissor;
206     float      fCachedBlendConstant[4];
207 
208     // Tracking of memory barriers so that we can submit them all in a batch together.
209     skia_private::STArray<1, VkBufferMemoryBarrier> fBufferBarriers;
210     skia_private::STArray<2, VkImageMemoryBarrier> fImageBarriers;
211     bool fBarriersByRegion = false;
212     VkPipelineStageFlags fSrcStageMask = 0;
213     VkPipelineStageFlags fDstStageMask = 0;
214 
215     bool fIsWrapped;
216 };
217 
218 class GrVkSecondaryCommandBuffer;
219 
220 class GrVkPrimaryCommandBuffer : public GrVkCommandBuffer {
221 public:
222     ~GrVkPrimaryCommandBuffer() override;
223 
224     static GrVkPrimaryCommandBuffer* Create(GrVkGpu* gpu, VkCommandPool cmdPool);
225 
226     void begin(GrVkGpu* gpu);
227     void end(GrVkGpu* gpu, bool abandoningBuffer = false);
228 
229     // Begins render pass on this command buffer. The framebuffer from GrVkRenderTarget will be used
230     // in the render pass.
231     bool beginRenderPass(GrVkGpu* gpu,
232                          const GrVkRenderPass*,
233                          sk_sp<const GrVkFramebuffer>,
234                          const VkClearValue clearValues[],
235                          const GrSurface* target,
236                          const SkIRect& bounds,
237                          bool forSecondaryCB);
238     void endRenderPass(const GrVkGpu* gpu);
239 
240     void nexSubpass(GrVkGpu* gpu, bool forSecondaryCB);
241 
242     // Submits the SecondaryCommandBuffer into this command buffer. It is required that we are
243     // currently inside a render pass that is compatible with the one used to create the
244     // SecondaryCommandBuffer.
245     void executeCommands(const GrVkGpu* gpu,
246                          std::unique_ptr<GrVkSecondaryCommandBuffer> secondaryBuffer);
247 
248     // Commands that only work outside of a render pass
249     void clearColorImage(const GrVkGpu* gpu,
250                          GrVkImage* image,
251                          const VkClearColorValue* color,
252                          uint32_t subRangeCount,
253                          const VkImageSubresourceRange* subRanges);
254 
255     void clearDepthStencilImage(const GrVkGpu* gpu,
256                                 GrVkImage* image,
257                                 const VkClearDepthStencilValue* color,
258                                 uint32_t subRangeCount,
259                                 const VkImageSubresourceRange* subRanges);
260 
261     void copyImage(const GrVkGpu* gpu,
262                    GrVkImage* srcImage,
263                    VkImageLayout srcLayout,
264                    GrVkImage* dstImage,
265                    VkImageLayout dstLayout,
266                    uint32_t copyRegionCount,
267                    const VkImageCopy* copyRegions);
268 
269     void blitImage(const GrVkGpu* gpu,
270                    const GrManagedResource* srcResource,
271                    VkImage srcImage,
272                    VkImageLayout srcLayout,
273                    const GrManagedResource* dstResource,
274                    VkImage dstImage,
275                    VkImageLayout dstLayout,
276                    uint32_t blitRegionCount,
277                    const VkImageBlit* blitRegions,
278                    VkFilter filter);
279 
280     void blitImage(const GrVkGpu* gpu,
281                    const GrVkImage& srcImage,
282                    const GrVkImage& dstImage,
283                    uint32_t blitRegionCount,
284                    const VkImageBlit* blitRegions,
285                    VkFilter filter);
286 
287     void copyImageToBuffer(const GrVkGpu* gpu,
288                            GrVkImage* srcImage,
289                            VkImageLayout srcLayout,
290                            sk_sp<GrGpuBuffer> dstBuffer,
291                            uint32_t copyRegionCount,
292                            const VkBufferImageCopy* copyRegions);
293 
294     // All uses of copyBufferToImage are done with buffers from our staging manager. The staging
295     // manager will handle making sure the command buffer refs the buffer. Thus we just pass in the
296     // raw VkBuffer here and don't worry about refs.
297     void copyBufferToImage(const GrVkGpu* gpu,
298                            VkBuffer srcBuffer,
299                            GrVkImage* dstImage,
300                            VkImageLayout dstLayout,
301                            uint32_t copyRegionCount,
302                            const VkBufferImageCopy* copyRegions);
303 
304     void fillBuffer(GrVkGpu* gpu,
305                     sk_sp<GrGpuBuffer>,
306                     VkDeviceSize offset,
307                     VkDeviceSize size,
308                     uint32_t data);
309 
310     void copyBuffer(GrVkGpu* gpu,
311                     sk_sp<GrGpuBuffer> srcBuffer,
312                     sk_sp<GrGpuBuffer> dstBuffer,
313                     uint32_t regionCount,
314                     const VkBufferCopy* regions);
315 
316     void updateBuffer(GrVkGpu* gpu,
317                       sk_sp<GrVkBuffer> dstBuffer,
318                       VkDeviceSize dstOffset,
319                       VkDeviceSize dataSize,
320                       const void* data);
321 
322     void resolveImage(GrVkGpu* gpu,
323                       const GrVkImage& srcImage,
324                       const GrVkImage& dstImage,
325                       uint32_t regionCount,
326                       const VkImageResolve* regions);
327 
328     bool submitToQueue(GrVkGpu* gpu,
329                        VkQueue queue,
330                        skia_private::TArray<GrVkSemaphore::Resource*>& signalSemaphores,
331                        skia_private::TArray<GrVkSemaphore::Resource*>& waitSemaphores,
332                        const GrSubmitInfo&);
333 
334     void forceSync(GrVkGpu* gpu);
335 
336     bool finished(GrVkGpu* gpu);
337 
338     void addFinishedProc(sk_sp<skgpu::RefCntedCallback> finishedProc);
339 
callFinishedProcs()340     void callFinishedProcs() {
341         fFinishedProcs.clear();
342     }
343 
344     void recycleSecondaryCommandBuffers(GrVkCommandPool* cmdPool);
345 
346 private:
GrVkPrimaryCommandBuffer(VkCommandBuffer cmdBuffer)347     explicit GrVkPrimaryCommandBuffer(VkCommandBuffer cmdBuffer)
348         : INHERITED(cmdBuffer)
349         , fSubmitFence(VK_NULL_HANDLE) {}
350 
351     void onFreeGPUData(const GrVkGpu* gpu) const override;
352 
353     void onReleaseResources() override;
354 
355     skia_private::TArray<std::unique_ptr<GrVkSecondaryCommandBuffer>, true> fSecondaryCommandBuffers;
356     VkFence                                                     fSubmitFence;
357     skia_private::TArray<sk_sp<skgpu::RefCntedCallback>>                    fFinishedProcs;
358 
359     using INHERITED = GrVkCommandBuffer;
360 };
361 
362 class GrVkSecondaryCommandBuffer : public GrVkCommandBuffer {
363 public:
364     static GrVkSecondaryCommandBuffer* Create(GrVkGpu* gpu, GrVkCommandPool* cmdPool);
365     // Used for wrapping an external secondary command buffer.
366     static GrVkSecondaryCommandBuffer* Create(VkCommandBuffer externalSecondaryCB,
367                                               const GrVkRenderPass* externalRenderPass);
368 
369     void begin(GrVkGpu* gpu, const GrVkFramebuffer* framebuffer,
370                const GrVkRenderPass* compatibleRenderPass);
371     void end(GrVkGpu* gpu);
372 
373     void recycle(GrVkCommandPool* cmdPool);
374 
vkCommandBuffer()375     VkCommandBuffer vkCommandBuffer() { return fCmdBuffer; }
376 
377 private:
GrVkSecondaryCommandBuffer(VkCommandBuffer cmdBuffer,const GrVkRenderPass * externalRenderPass)378     explicit GrVkSecondaryCommandBuffer(VkCommandBuffer cmdBuffer,
379                                         const GrVkRenderPass* externalRenderPass)
380             : INHERITED(cmdBuffer, SkToBool(externalRenderPass)) {
381         fActiveRenderPass = externalRenderPass;
382     }
383 
onFreeGPUData(const GrVkGpu * gpu)384     void onFreeGPUData(const GrVkGpu* gpu) const override {}
385 
386     // Used for accessing fIsActive (on GrVkCommandBuffer)
387     friend class GrVkPrimaryCommandBuffer;
388 
389     using INHERITED = GrVkCommandBuffer;
390 };
391 
392 #endif
393