• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/gpu/vk/GrVkTypes.h"
12 #include "src/gpu/vk/GrVkGpu.h"
13 #include "src/gpu/vk/GrVkResource.h"
14 #include "src/gpu/vk/GrVkSemaphore.h"
15 #include "src/gpu/vk/GrVkUtil.h"
16 
17 class GrVkBuffer;
18 class GrVkFramebuffer;
19 class GrVkIndexBuffer;
20 class GrVkImage;
21 class GrVkPipeline;
22 class GrVkPipelineState;
23 class GrVkRenderPass;
24 class GrVkRenderTarget;
25 class GrVkTransferBuffer;
26 class GrVkVertexBuffer;
27 
28 class GrVkCommandBuffer {
29 public:
~GrVkCommandBuffer()30     virtual ~GrVkCommandBuffer() {}
31 
32     void invalidateState();
33 
34     ////////////////////////////////////////////////////////////////////////////
35     // CommandBuffer commands
36     ////////////////////////////////////////////////////////////////////////////
37     enum BarrierType {
38         kBufferMemory_BarrierType,
39         kImageMemory_BarrierType
40     };
41 
42     void pipelineBarrier(const GrVkGpu* gpu,
43                          const GrVkResource* resource,
44                          VkPipelineStageFlags srcStageMask,
45                          VkPipelineStageFlags dstStageMask,
46                          bool byRegion,
47                          BarrierType barrierType,
48                          void* barrier);
49 
50     void bindInputBuffer(GrVkGpu* gpu, uint32_t binding, const GrVkVertexBuffer* vbuffer);
51 
52     void bindIndexBuffer(GrVkGpu* gpu, const GrVkIndexBuffer* ibuffer);
53 
54     void bindPipeline(const GrVkGpu* gpu, const GrVkPipeline* pipeline);
55 
56     void bindDescriptorSets(const GrVkGpu* gpu,
57                             GrVkPipelineState*,
58                             VkPipelineLayout layout,
59                             uint32_t firstSet,
60                             uint32_t setCount,
61                             const VkDescriptorSet* descriptorSets,
62                             uint32_t dynamicOffsetCount,
63                             const uint32_t* dynamicOffsets);
64 
commandPool()65     GrVkCommandPool* commandPool() { return fCmdPool; }
66 
67     void setViewport(const GrVkGpu* gpu,
68                      uint32_t firstViewport,
69                      uint32_t viewportCount,
70                      const VkViewport* viewports);
71 
72     void setScissor(const GrVkGpu* gpu,
73                     uint32_t firstScissor,
74                     uint32_t scissorCount,
75                     const VkRect2D* scissors);
76 
77     void setBlendConstants(const GrVkGpu* gpu, const float blendConstants[4]);
78 
79     // Commands that only work inside of a render pass
80     void clearAttachments(const GrVkGpu* gpu,
81                           int numAttachments,
82                           const VkClearAttachment* attachments,
83                           int numRects,
84                           const VkClearRect* clearRects);
85 
86     void drawIndexed(const GrVkGpu* gpu,
87                      uint32_t indexCount,
88                      uint32_t instanceCount,
89                      uint32_t firstIndex,
90                      int32_t vertexOffset,
91                      uint32_t firstInstance);
92 
93     void draw(const GrVkGpu* gpu,
94               uint32_t vertexCount,
95               uint32_t instanceCount,
96               uint32_t firstVertex,
97               uint32_t firstInstance);
98 
99     // Add ref-counted resource that will be tracked and released when this command buffer finishes
100     // execution
addResource(const GrVkResource * resource)101     void addResource(const GrVkResource* resource) {
102         resource->ref();
103         resource->notifyAddedToCommandBuffer();
104         fTrackedResources.append(1, &resource);
105     }
106 
107     // Add ref-counted resource that will be tracked and released when this command buffer finishes
108     // execution. When it is released, it will signal that the resource can be recycled for reuse.
addRecycledResource(const GrVkRecycledResource * resource)109     void addRecycledResource(const GrVkRecycledResource* resource) {
110         resource->ref();
111         resource->notifyAddedToCommandBuffer();
112         fTrackedRecycledResources.append(1, &resource);
113     }
114 
115     void releaseResources(GrVkGpu* gpu);
116 
117     void freeGPUData(GrVkGpu* gpu) const;
118     void abandonGPUData() const;
119 
hasWork()120     bool hasWork() const { return fHasWork; }
121 
122 protected:
123     GrVkCommandBuffer(VkCommandBuffer cmdBuffer, GrVkCommandPool* cmdPool,
124                       const GrVkRenderPass* rp = nullptr)
fIsActive(false)125             : fIsActive(false)
126             , fActiveRenderPass(rp)
127             , fCmdBuffer(cmdBuffer)
128             , fCmdPool(cmdPool)
129             , fNumResets(0) {
130         fTrackedResources.setReserve(kInitialTrackedResourcesCount);
131         fTrackedRecycledResources.setReserve(kInitialTrackedResourcesCount);
132         this->invalidateState();
133     }
134 
isWrapped()135     bool isWrapped() const { return fCmdPool == nullptr; }
136 
137     void addingWork(const GrVkGpu* gpu);
138 
139     void submitPipelineBarriers(const GrVkGpu* gpu);
140 
141     SkTDArray<const GrVkResource*>          fTrackedResources;
142     SkTDArray<const GrVkRecycledResource*>  fTrackedRecycledResources;
143 
144     // Tracks whether we are in the middle of a command buffer begin/end calls and thus can add
145     // new commands to the buffer;
146     bool                      fIsActive;
147     bool                      fHasWork = false;
148 
149     // Stores a pointer to the current active render pass (i.e. begin has been called but not
150     // end). A nullptr means there is no active render pass. The GrVKCommandBuffer does not own
151     // the render pass.
152     const GrVkRenderPass*     fActiveRenderPass;
153 
154     VkCommandBuffer           fCmdBuffer;
155 
156     // Raw pointer, not refcounted. The command pool controls the command buffer's lifespan, so
157     // it's guaranteed to outlive us.
158     GrVkCommandPool*          fCmdPool;
159 
160 private:
161     static const int kInitialTrackedResourcesCount = 32;
162 
onReleaseResources(GrVkGpu * gpu)163     virtual void onReleaseResources(GrVkGpu* gpu) {}
164     virtual void onFreeGPUData(GrVkGpu* gpu) const = 0;
165     virtual void onAbandonGPUData() const = 0;
166 
167     static constexpr uint32_t kMaxInputBuffers = 2;
168 
169     VkBuffer fBoundInputBuffers[kMaxInputBuffers];
170     VkBuffer fBoundIndexBuffer;
171 
172     // When resetting the command buffer, we remove the tracked resources from their arrays, and
173     // we prefer to not free all the memory every time so usually we just rewind. However, to avoid
174     // all arrays growing to the max size, after so many resets we'll do a full reset of the tracked
175     // resource arrays.
176     static const int kNumRewindResetsBeforeFullReset = 8;
177     int              fNumResets;
178 
179     // Cached values used for dynamic state updates
180     VkViewport fCachedViewport;
181     VkRect2D   fCachedScissor;
182     float      fCachedBlendConstant[4];
183 
184 #ifdef SK_DEBUG
185     mutable bool fResourcesReleased = false;
186 #endif
187     // Tracking of memory barriers so that we can submit them all in a batch together.
188     SkSTArray<4, VkBufferMemoryBarrier> fBufferBarriers;
189     SkSTArray<1, VkImageMemoryBarrier> fImageBarriers;
190     bool fBarriersByRegion = false;
191     VkPipelineStageFlags fSrcStageMask = 0;
192     VkPipelineStageFlags fDstStageMask = 0;
193 };
194 
195 class GrVkSecondaryCommandBuffer;
196 
197 class GrVkPrimaryCommandBuffer : public GrVkCommandBuffer {
198 public:
199     ~GrVkPrimaryCommandBuffer() override;
200 
201     static GrVkPrimaryCommandBuffer* Create(const GrVkGpu* gpu, GrVkCommandPool* cmdPool);
202 
203     void begin(const GrVkGpu* gpu);
204     void end(GrVkGpu* gpu);
205 
206     // Begins render pass on this command buffer. The framebuffer from GrVkRenderTarget will be used
207     // in the render pass.
208     void beginRenderPass(const GrVkGpu* gpu,
209                          const GrVkRenderPass* renderPass,
210                          const VkClearValue clearValues[],
211                          const GrVkRenderTarget& target,
212                          const SkIRect& bounds,
213                          bool forSecondaryCB);
214     void endRenderPass(const GrVkGpu* gpu);
215 
216     // Submits the SecondaryCommandBuffer into this command buffer. It is required that we are
217     // currently inside a render pass that is compatible with the one used to create the
218     // SecondaryCommandBuffer.
219     void executeCommands(const GrVkGpu* gpu,
220                          std::unique_ptr<GrVkSecondaryCommandBuffer> secondaryBuffer);
221 
222     // Commands that only work outside of a render pass
223     void clearColorImage(const GrVkGpu* gpu,
224                          GrVkImage* image,
225                          const VkClearColorValue* color,
226                          uint32_t subRangeCount,
227                          const VkImageSubresourceRange* subRanges);
228 
229     void clearDepthStencilImage(const GrVkGpu* gpu,
230                                 GrVkImage* image,
231                                 const VkClearDepthStencilValue* color,
232                                 uint32_t subRangeCount,
233                                 const VkImageSubresourceRange* subRanges);
234 
235     void copyImage(const GrVkGpu* gpu,
236                    GrVkImage* srcImage,
237                    VkImageLayout srcLayout,
238                    GrVkImage* dstImage,
239                    VkImageLayout dstLayout,
240                    uint32_t copyRegionCount,
241                    const VkImageCopy* copyRegions);
242 
243     void blitImage(const GrVkGpu* gpu,
244                    const GrVkResource* srcResource,
245                    VkImage srcImage,
246                    VkImageLayout srcLayout,
247                    const GrVkResource* dstResource,
248                    VkImage dstImage,
249                    VkImageLayout dstLayout,
250                    uint32_t blitRegionCount,
251                    const VkImageBlit* blitRegions,
252                    VkFilter filter);
253 
254     void blitImage(const GrVkGpu* gpu,
255                    const GrVkImage& srcImage,
256                    const GrVkImage& dstImage,
257                    uint32_t blitRegionCount,
258                    const VkImageBlit* blitRegions,
259                    VkFilter filter);
260 
261     void copyImageToBuffer(const GrVkGpu* gpu,
262                            GrVkImage* srcImage,
263                            VkImageLayout srcLayout,
264                            GrVkTransferBuffer* dstBuffer,
265                            uint32_t copyRegionCount,
266                            const VkBufferImageCopy* copyRegions);
267 
268     void copyBufferToImage(const GrVkGpu* gpu,
269                            GrVkTransferBuffer* srcBuffer,
270                            GrVkImage* dstImage,
271                            VkImageLayout dstLayout,
272                            uint32_t copyRegionCount,
273                            const VkBufferImageCopy* copyRegions);
274 
275     void copyBuffer(GrVkGpu* gpu,
276                     GrVkBuffer* srcBuffer,
277                     GrVkBuffer* dstBuffer,
278                     uint32_t regionCount,
279                     const VkBufferCopy* regions);
280 
281     void updateBuffer(GrVkGpu* gpu,
282                       GrVkBuffer* dstBuffer,
283                       VkDeviceSize dstOffset,
284                       VkDeviceSize dataSize,
285                       const void* data);
286 
287     void resolveImage(GrVkGpu* gpu,
288                       const GrVkImage& srcImage,
289                       const GrVkImage& dstImage,
290                       uint32_t regionCount,
291                       const VkImageResolve* regions);
292 
293     void submitToQueue(const GrVkGpu* gpu, VkQueue queue, GrVkGpu::SyncQueue sync,
294                        SkTArray<GrVkSemaphore::Resource*>& signalSemaphores,
295                        SkTArray<GrVkSemaphore::Resource*>& waitSemaphores);
296     bool finished(const GrVkGpu* gpu);
297 
298     void addFinishedProc(sk_sp<GrRefCntedCallback> finishedProc);
299 
300     void recycleSecondaryCommandBuffers(GrVkGpu* gpu);
301 
302 private:
GrVkPrimaryCommandBuffer(VkCommandBuffer cmdBuffer,GrVkCommandPool * cmdPool)303     explicit GrVkPrimaryCommandBuffer(VkCommandBuffer cmdBuffer, GrVkCommandPool* cmdPool)
304         : INHERITED(cmdBuffer, cmdPool)
305         , fSubmitFence(VK_NULL_HANDLE) {}
306 
307     void onFreeGPUData(GrVkGpu* gpu) const override;
308 
309     void onAbandonGPUData() const override;
310 
311     void onReleaseResources(GrVkGpu* gpu) override;
312 
313     SkTArray<std::unique_ptr<GrVkSecondaryCommandBuffer>, true> fSecondaryCommandBuffers;
314     VkFence                                                     fSubmitFence;
315     SkTArray<sk_sp<GrRefCntedCallback>>                         fFinishedProcs;
316 
317     typedef GrVkCommandBuffer INHERITED;
318 };
319 
320 class GrVkSecondaryCommandBuffer : public GrVkCommandBuffer {
321 public:
322     static GrVkSecondaryCommandBuffer* Create(const GrVkGpu* gpu, GrVkCommandPool* cmdPool);
323     // Used for wrapping an external secondary command buffer.
324     static GrVkSecondaryCommandBuffer* Create(VkCommandBuffer externalSecondaryCB);
325 
326     void begin(const GrVkGpu* gpu, const GrVkFramebuffer* framebuffer,
327                const GrVkRenderPass* compatibleRenderPass);
328     void end(GrVkGpu* gpu);
329 
330     void recycle(GrVkGpu* gpu);
331 
vkCommandBuffer()332     VkCommandBuffer vkCommandBuffer() { return fCmdBuffer; }
333 
334 private:
GrVkSecondaryCommandBuffer(VkCommandBuffer cmdBuffer,GrVkCommandPool * cmdPool)335     explicit GrVkSecondaryCommandBuffer(VkCommandBuffer cmdBuffer, GrVkCommandPool* cmdPool)
336         : INHERITED(cmdBuffer, cmdPool) {}
337 
onFreeGPUData(GrVkGpu * gpu)338     void onFreeGPUData(GrVkGpu* gpu) const override {}
339 
onAbandonGPUData()340     void onAbandonGPUData() const override {}
341 
342     friend class GrVkPrimaryCommandBuffer;
343 
344     typedef GrVkCommandBuffer INHERITED;
345 };
346 
347 #endif
348