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

#ifndef skgpu_DrawPass_DEFINED
#define skgpu_DrawPass_DEFINED

#include "experimental/graphite/src/DrawTypes.h"
#include "experimental/graphite/src/GraphicsPipelineDesc.h"
#include "experimental/graphite/src/ResourceTypes.h"
#include "include/core/SkColor.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "src/core/SkTBlockList.h"

#include <memory>

namespace skgpu {

class BoundsManager;
class CommandBuffer;
class DrawList;
class Recorder;
struct RenderPassDesc;
class ResourceProvider;
class TextureProxy;
enum class UniformSlot;

/**
 * DrawPass is analogous to a subpass, storing the drawing operations in the order they are stored
 * in the eventual command buffer, as well as the surface proxy the operations are intended for.
 * DrawPasses are grouped into a RenderPassTask for execution within a single render pass if the
 * subpasses are compatible with each other.
 *
 * Unlike DrawList, DrawPasses are immutable and represent as closely as possible what will be
 * stored in the command buffer while being flexible as to how the pass is incorporated. Depending
 * on the backend, it may even be able to write accumulated vertex and uniform data directly to
 * mapped GPU memory, although that is the extent of the CPU->GPU work they perform before they are
 * executed by a RenderPassTask.
 */
class DrawPass {
public:
    ~DrawPass();

    // TODO: Replace SDC with the SDC's surface proxy view
    static std::unique_ptr<DrawPass> Make(Recorder*,
                                          std::unique_ptr<DrawList>,
                                          sk_sp<TextureProxy>,
                                          std::pair<LoadOp, StoreOp>,
                                          std::array<float, 4> clearColor,
                                          const BoundsManager* occlusionCuller);

    // Defined relative to the top-left corner of the surface the DrawPass renders to, and is
    // contained within its dimensions.
    const SkIRect&      bounds() const { return fBounds;       }
    TextureProxy* target() const { return fTarget.get(); }
    std::pair<LoadOp, StoreOp> ops() const { return fOps; }
    std::array<float, 4> clearColor() const { return fClearColor; }

    bool requiresDstTexture() const { return false;            }
    bool requiresMSAA()       const { return fRequiresMSAA;    }

    Mask<DepthStencilFlags> depthStencilFlags() const { return fDepthStencilFlags; }

    size_t vertexBufferSize()  const { return 0; }
    size_t uniformBufferSize() const { return 0; }

    // TODO: Real return types, but it seems useful for DrawPass to report these as sets so that
    // task execution can compile necessary programs and track resources within a render pass.
    // Maybe these won't need to be exposed and RenderPassTask can do it per command as needed when
    // it iterates over the DrawPass contents.
    void samplers() const {}
    void programs() const {}

    // Transform this DrawPass into commands issued to the CommandBuffer. Assumes that the buffer
    // has already begun a correctly configured render pass matching this pass's target.
    void addCommands(ResourceProvider*, CommandBuffer*, const RenderPassDesc&) const;

private:
    class SortKey;
    class Drawer;

    struct BindGraphicsPipeline {
        // Points to a GraphicsPipelineDesc in DrawPass's fPipelineDescs array. It will also
        // index into a parallel array of full GraphicsPipelines when commands are added to the CB.
        uint32_t fPipelineIndex;
    };
    struct BindUniformBuffer {
        BindBufferInfo fInfo;
        UniformSlot fSlot;
    };
    struct BindDrawBuffers {
        BindBufferInfo fVertices;
        BindBufferInfo fInstances;
        BindBufferInfo fIndices;
    };
    struct Draw {
        PrimitiveType fType;
        uint32_t fBaseVertex;
        uint32_t fVertexCount;
    };
    struct DrawIndexed {
        PrimitiveType fType;
        uint32_t fBaseIndex;
        uint32_t fIndexCount;
        uint32_t fBaseVertex;
    };
    struct DrawInstanced {
        PrimitiveType fType;
        uint32_t fBaseVertex;
        uint32_t fVertexCount;
        uint32_t fBaseInstance;
        uint32_t fInstanceCount;
    };
    struct DrawIndexedInstanced {
        PrimitiveType fType;
        uint32_t fBaseIndex;
        uint32_t fIndexCount;
        uint32_t fBaseVertex;
        uint32_t fBaseInstance;
        uint32_t fInstanceCount;
    };
    struct SetScissor {
        SkIRect fScissor;
    };

    // TODO: BindSampler

    enum class CommandType {
        kBindGraphicsPipeline,
        kBindUniformBuffer,
        kBindDrawBuffers,
        kDraw,
        kDrawIndexed,
        kDrawInstanced,
        kDrawIndexedInstanced,
        kSetScissor,
        // kBindSampler
    };
    // TODO: The goal is keep all command data in line, vs. type + void* to another data array, but
    // the current union is memory inefficient. It would be better to have a byte buffer with per
    // type advances, but then we need to work out alignment etc. so that will be easier to add
    // once we have something up and running.
    struct Command {
        CommandType fType;
        union {
            BindGraphicsPipeline fBindGraphicsPipeline;
            BindUniformBuffer    fBindUniformBuffer;
            BindDrawBuffers      fBindDrawBuffers;
            Draw                 fDraw;
            DrawIndexed          fDrawIndexed;
            DrawInstanced        fDrawInstanced;
            DrawIndexedInstanced fDrawIndexedInstanced;
            SetScissor           fSetScissor;
        };

        explicit Command(BindGraphicsPipeline d)
                : fType(CommandType::kBindGraphicsPipeline), fBindGraphicsPipeline(d) {}
        explicit Command(BindUniformBuffer d)
                : fType(CommandType::kBindUniformBuffer), fBindUniformBuffer(d) {}
        explicit Command(BindDrawBuffers d)
                : fType(CommandType::kBindDrawBuffers), fBindDrawBuffers(d) {}
        explicit Command(Draw d)
                : fType(CommandType::kDraw), fDraw(d) {}
        explicit Command(DrawIndexed d)
                : fType(CommandType::kDrawIndexed), fDrawIndexed(d) {}
        explicit Command(DrawInstanced d)
                : fType(CommandType::kDrawInstanced), fDrawInstanced(d) {}
        explicit Command(DrawIndexedInstanced d)
                : fType(CommandType::kDrawIndexedInstanced), fDrawIndexedInstanced(d) {}
        explicit Command(SetScissor d)
                : fType(CommandType::kSetScissor), fSetScissor(d) {}
    };
    // Not strictly necessary, but keeping Command trivially destructible means the command list
    // can be cleaned up efficiently once it's converted to a command buffer.
    static_assert(std::is_trivially_destructible<Command>::value);

    DrawPass(sk_sp<TextureProxy> target,
             std::pair<LoadOp, StoreOp> ops,
             std::array<float, 4> clearColor,
             int renderStepCount);

    SkTBlockList<Command, 32> fCommands;
    // The pipelines are referenced by index in BindGraphicsPipeline, but that will index into a
    // an array of actual GraphicsPipelines. fPipelineDescs only needs to accumulate encountered
    // GraphicsPipelineDescs and provide stable pointers, hence SkTBlockList.
    SkTBlockList<GraphicsPipelineDesc, 32> fPipelineDescs;

    sk_sp<TextureProxy> fTarget;
    SkIRect             fBounds;

    std::pair<LoadOp, StoreOp> fOps;
    std::array<float, 4>       fClearColor;

    Mask<DepthStencilFlags> fDepthStencilFlags = DepthStencilFlags::kNone;
    bool                    fRequiresMSAA = false;
};

} // namespace skgpu

#endif // skgpu_DrawPass_DEFINED
