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