/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/

#ifndef GrVkCommandBuffer_DEFINED
#define GrVkCommandBuffer_DEFINED

#include "include/gpu/vk/GrVkTypes.h"
#include "src/gpu/GrManagedResource.h"
#include "src/gpu/GrRefCnt.h"
#include "src/gpu/vk/GrVkGpu.h"
#include "src/gpu/vk/GrVkSemaphore.h"
#include "src/gpu/vk/GrVkUtil.h"

class GrVkFramebuffer;
class GrVkImage;
class GrVkPipeline;
class GrVkPipelineState;
class GrVkRenderPass;
class GrVkRenderTarget;

class GrVkCommandBuffer {
public:
    virtual ~GrVkCommandBuffer() {}

    void invalidateState();

    ////////////////////////////////////////////////////////////////////////////
    // CommandBuffer commands
    ////////////////////////////////////////////////////////////////////////////
    enum BarrierType {
        kBufferMemory_BarrierType,
        kImageMemory_BarrierType
    };

    void pipelineBarrier(const GrVkGpu* gpu,
                         const GrManagedResource* resource,
                         VkPipelineStageFlags srcStageMask,
                         VkPipelineStageFlags dstStageMask,
                         bool byRegion,
                         BarrierType barrierType,
                         void* barrier);

    void bindInputBuffer(GrVkGpu* gpu, uint32_t binding, sk_sp<const GrBuffer> buffer);

    void bindIndexBuffer(GrVkGpu* gpu, sk_sp<const GrBuffer> buffer);

    void bindPipeline(const GrVkGpu* gpu, sk_sp<const GrVkPipeline> pipeline);

    void bindDescriptorSets(const GrVkGpu* gpu,
                            VkPipelineLayout layout,
                            uint32_t firstSet,
                            uint32_t setCount,
                            const VkDescriptorSet* descriptorSets,
                            uint32_t dynamicOffsetCount,
                            const uint32_t* dynamicOffsets);

    void pushConstants(const GrVkGpu* gpu, VkPipelineLayout layout,
                       VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size,
                       const void* values);

    void setViewport(const GrVkGpu* gpu,
                     uint32_t firstViewport,
                     uint32_t viewportCount,
                     const VkViewport* viewports);

    void setScissor(const GrVkGpu* gpu,
                    uint32_t firstScissor,
                    uint32_t scissorCount,
                    const VkRect2D* scissors);

    void setBlendConstants(const GrVkGpu* gpu, const float blendConstants[4]);

    // Commands that only work inside of a render pass
    void clearAttachments(const GrVkGpu* gpu,
                          int numAttachments,
                          const VkClearAttachment* attachments,
                          int numRects,
                          const VkClearRect* clearRects);

    void drawIndexed(const GrVkGpu* gpu,
                     uint32_t indexCount,
                     uint32_t instanceCount,
                     uint32_t firstIndex,
                     int32_t vertexOffset,
                     uint32_t firstInstance);

    void draw(const GrVkGpu* gpu,
              uint32_t vertexCount,
              uint32_t instanceCount,
              uint32_t firstVertex,
              uint32_t firstInstance);

    void drawIndirect(const GrVkGpu* gpu,
                      sk_sp<const GrBuffer> indirectBuffer,
                      VkDeviceSize offset,
                      uint32_t drawCount,
                      uint32_t stride);

    void drawIndexedIndirect(const GrVkGpu* gpu,
                             sk_sp<const GrBuffer> indirectBuffer,
                             VkDeviceSize offset,
                             uint32_t drawCount,
                             uint32_t stride);

    // Add ref-counted resource that will be tracked and released when this command buffer finishes
    // execution
    void addResource(sk_sp<const GrManagedResource> resource) {
        SkASSERT(resource);
        fTrackedResources.push_back(std::move(resource));
    }
    void addResource(const GrManagedResource* resource) {
        this->addResource(sk_ref_sp(resource));
    }

    // Add ref-counted resource that will be tracked and released when this command buffer finishes
    // execution. When it is released, it will signal that the resource can be recycled for reuse.
    void addRecycledResource(gr_rp<const GrRecycledResource> resource) {
        SkASSERT(resource);
        fTrackedRecycledResources.push_back(std::move(resource));
    }

    void addRecycledResource(const GrRecycledResource* resource) {
        this->addRecycledResource(gr_ref_rp<const GrRecycledResource>(resource));
    }

    void addGrBuffer(sk_sp<const GrBuffer> buffer) {
        fTrackedGpuBuffers.push_back(std::move(buffer));
    }

    void addGrSurface(sk_sp<const GrSurface> surface) {
        fTrackedGpuSurfaces.push_back(std::move(surface));
    }

    void releaseResources();

    void freeGPUData(const GrGpu* gpu, VkCommandPool pool) const;

    bool hasWork() const { return fHasWork; }

protected:
    GrVkCommandBuffer(VkCommandBuffer cmdBuffer, bool isWrapped = false)
            : fIsActive(isWrapped) // All wrapped command buffers start as active
            , fCmdBuffer(cmdBuffer)
            , fIsWrapped(isWrapped) {
        this->invalidateState();
    }

    bool isWrapped() const { return fIsWrapped; }

    void addingWork(const GrVkGpu* gpu);

    void submitPipelineBarriers(const GrVkGpu* gpu, bool forSelfDependency = false);

private:
    static constexpr int kInitialTrackedResourcesCount = 32;

protected:
    template <typename T> using TrackedResourceArray = SkSTArray<kInitialTrackedResourcesCount, T>;
    TrackedResourceArray<sk_sp<const GrManagedResource>> fTrackedResources;
    TrackedResourceArray<gr_rp<const GrRecycledResource>> fTrackedRecycledResources;
    SkSTArray<16, sk_sp<const GrBuffer>> fTrackedGpuBuffers;
    SkSTArray<16, gr_cb<const GrSurface>> fTrackedGpuSurfaces;

    // Tracks whether we are in the middle of a command buffer begin/end calls and thus can add
    // new commands to the buffer;
    bool                      fIsActive;
    bool                      fHasWork = false;

    // Stores a pointer to the current active render pass (i.e. begin has been called but not
    // end). A nullptr means there is no active render pass. The GrVKCommandBuffer does not own
    // the render pass.
    const GrVkRenderPass*     fActiveRenderPass = nullptr;

    VkCommandBuffer           fCmdBuffer;

    virtual void onReleaseResources() {}
    virtual void onFreeGPUData(const GrVkGpu* gpu) const = 0;

    static constexpr uint32_t kMaxInputBuffers = 2;

    VkBuffer fBoundInputBuffers[kMaxInputBuffers];
    VkBuffer fBoundIndexBuffer;

    // Cached values used for dynamic state updates
    VkViewport fCachedViewport;
    VkRect2D   fCachedScissor;
    float      fCachedBlendConstant[4];

    // Tracking of memory barriers so that we can submit them all in a batch together.
    SkSTArray<1, VkBufferMemoryBarrier> fBufferBarriers;
    SkSTArray<2, VkImageMemoryBarrier> fImageBarriers;
    bool fBarriersByRegion = false;
    VkPipelineStageFlags fSrcStageMask = 0;
    VkPipelineStageFlags fDstStageMask = 0;

    bool fIsWrapped;
};

class GrVkSecondaryCommandBuffer;

class GrVkPrimaryCommandBuffer : public GrVkCommandBuffer {
public:
    ~GrVkPrimaryCommandBuffer() override;

    static GrVkPrimaryCommandBuffer* Create(GrVkGpu* gpu, VkCommandPool cmdPool);

    void begin(GrVkGpu* gpu);
    void end(GrVkGpu* gpu, bool abandoningBuffer = false);

    // Begins render pass on this command buffer. The framebuffer from GrVkRenderTarget will be used
    // in the render pass.
    bool beginRenderPass(GrVkGpu* gpu,
                         const GrVkRenderPass*,
                         sk_sp<const GrVkFramebuffer>,
                         const VkClearValue clearValues[],
                         const GrSurface* target,
                         const SkIRect& bounds,
                         bool forSecondaryCB);
    void endRenderPass(const GrVkGpu* gpu);

    void nexSubpass(GrVkGpu* gpu, bool forSecondaryCB);

    // Submits the SecondaryCommandBuffer into this command buffer. It is required that we are
    // currently inside a render pass that is compatible with the one used to create the
    // SecondaryCommandBuffer.
    void executeCommands(const GrVkGpu* gpu,
                         std::unique_ptr<GrVkSecondaryCommandBuffer> secondaryBuffer);

    // Commands that only work outside of a render pass
    void clearColorImage(const GrVkGpu* gpu,
                         GrVkImage* image,
                         const VkClearColorValue* color,
                         uint32_t subRangeCount,
                         const VkImageSubresourceRange* subRanges);

    void clearDepthStencilImage(const GrVkGpu* gpu,
                                GrVkImage* image,
                                const VkClearDepthStencilValue* color,
                                uint32_t subRangeCount,
                                const VkImageSubresourceRange* subRanges);

    void copyImage(const GrVkGpu* gpu,
                   GrVkImage* srcImage,
                   VkImageLayout srcLayout,
                   GrVkImage* dstImage,
                   VkImageLayout dstLayout,
                   uint32_t copyRegionCount,
                   const VkImageCopy* copyRegions);

    void blitImage(const GrVkGpu* gpu,
                   const GrManagedResource* srcResource,
                   VkImage srcImage,
                   VkImageLayout srcLayout,
                   const GrManagedResource* dstResource,
                   VkImage dstImage,
                   VkImageLayout dstLayout,
                   uint32_t blitRegionCount,
                   const VkImageBlit* blitRegions,
                   VkFilter filter);

    void blitImage(const GrVkGpu* gpu,
                   const GrVkImage& srcImage,
                   const GrVkImage& dstImage,
                   uint32_t blitRegionCount,
                   const VkImageBlit* blitRegions,
                   VkFilter filter);

    void copyImageToBuffer(const GrVkGpu* gpu,
                           GrVkImage* srcImage,
                           VkImageLayout srcLayout,
                           sk_sp<GrGpuBuffer> dstBuffer,
                           uint32_t copyRegionCount,
                           const VkBufferImageCopy* copyRegions);

    // All uses of copyBufferToImage are done with buffers from our staging manager. The staging
    // manager will handle making sure the command buffer refs the buffer. Thus we just pass in the
    // raw VkBuffer here and don't worry about refs.
    void copyBufferToImage(const GrVkGpu* gpu,
                           VkBuffer srcBuffer,
                           GrVkImage* dstImage,
                           VkImageLayout dstLayout,
                           uint32_t copyRegionCount,
                           const VkBufferImageCopy* copyRegions);

    void copyBuffer(GrVkGpu* gpu,
                    sk_sp<GrGpuBuffer> srcBuffer,
                    sk_sp<GrGpuBuffer> dstBuffer,
                    uint32_t regionCount,
                    const VkBufferCopy* regions);

    void updateBuffer(GrVkGpu* gpu,
                      sk_sp<GrVkBuffer> dstBuffer,
                      VkDeviceSize dstOffset,
                      VkDeviceSize dataSize,
                      const void* data);

    void resolveImage(GrVkGpu* gpu,
                      const GrVkImage& srcImage,
                      const GrVkImage& dstImage,
                      uint32_t regionCount,
                      const VkImageResolve* regions);

    bool submitToQueue(GrVkGpu* gpu, VkQueue queue,
                       SkTArray<GrVkSemaphore::Resource*>& signalSemaphores,
                       SkTArray<GrVkSemaphore::Resource*>& waitSemaphores);

    void forceSync(GrVkGpu* gpu);

    bool finished(GrVkGpu* gpu);

    void addFinishedProc(sk_sp<GrRefCntedCallback> finishedProc);

    void callFinishedProcs() {
        fFinishedProcs.reset();
    }

    void recycleSecondaryCommandBuffers(GrVkCommandPool* cmdPool);

private:
    explicit GrVkPrimaryCommandBuffer(VkCommandBuffer cmdBuffer)
        : INHERITED(cmdBuffer)
        , fSubmitFence(VK_NULL_HANDLE) {}

    void onFreeGPUData(const GrVkGpu* gpu) const override;

    void onReleaseResources() override;

    SkTArray<std::unique_ptr<GrVkSecondaryCommandBuffer>, true> fSecondaryCommandBuffers;
    VkFence                                                     fSubmitFence;
    SkTArray<sk_sp<GrRefCntedCallback>>                         fFinishedProcs;

    using INHERITED = GrVkCommandBuffer;
};

class GrVkSecondaryCommandBuffer : public GrVkCommandBuffer {
public:
    static GrVkSecondaryCommandBuffer* Create(GrVkGpu* gpu, GrVkCommandPool* cmdPool);
    // Used for wrapping an external secondary command buffer.
    static GrVkSecondaryCommandBuffer* Create(VkCommandBuffer externalSecondaryCB,
                                              const GrVkRenderPass* externalRenderPass);

    void begin(GrVkGpu* gpu, const GrVkFramebuffer* framebuffer,
               const GrVkRenderPass* compatibleRenderPass);
    void end(GrVkGpu* gpu);

    void recycle(GrVkCommandPool* cmdPool);

    VkCommandBuffer vkCommandBuffer() { return fCmdBuffer; }

private:
    explicit GrVkSecondaryCommandBuffer(VkCommandBuffer cmdBuffer,
                                        const GrVkRenderPass* externalRenderPass)
            : INHERITED(cmdBuffer, SkToBool(externalRenderPass)) {
        fActiveRenderPass = externalRenderPass;
    }

    void onFreeGPUData(const GrVkGpu* gpu) const override {}

    // Used for accessing fIsActive (on GrVkCommandBuffer)
    friend class GrVkPrimaryCommandBuffer;

    using INHERITED = GrVkCommandBuffer;
};

#endif
