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