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

#include "src/gpu/graphite/compute/VelloRenderer.h"

#include "include/core/SkPath.h"
#include "include/core/SkTypes.h"
#include "include/gpu/graphite/Recorder.h"
#include "src/core/SkGeometry.h"
#include "src/core/SkPathPriv.h"
#include "src/core/SkTraceEvent.h"
#include "src/gpu/graphite/BufferManager.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/DrawParams.h"
#include "src/gpu/graphite/Log.h"
#include "src/gpu/graphite/PipelineData.h"
#include "src/gpu/graphite/RecorderPriv.h"
#include "src/gpu/graphite/TextureProxy.h"
#include "src/gpu/graphite/TextureUtils.h"
#include "src/gpu/graphite/UniformManager.h"
#include "src/gpu/graphite/compute/DispatchGroup.h"
#include "src/gpu/graphite/geom/Transform.h"

#include <algorithm>

namespace skgpu::graphite {
namespace {

BindBufferInfo new_scratch_slice(BufferSubAllocator& scratch) {
    size_t size = scratch.remainingBytes();  // Use the whole buffer.
    return scratch.getSubrange(size, /*stride=*/1);
}

BindBufferInfo new_indirect_slice(DrawBufferManager* mgr, size_t size) {
   return  mgr->getIndirectStorage(size, ClearBuffer::kYes);
}

::rust::Slice<uint8_t> to_slice(SkSpan<uint8_t> slice) {
    return {slice.data(), slice.size_bytes()};
}

vello_cpp::Affine to_vello_affine(const SkMatrix& m) {
    // Vello currently doesn't support perspective scaling and the encoding only accepts a 2x3
    // affine transform matrix.
    return {{m.get(0), m.get(3), m.get(1), m.get(4), m.get(2), m.get(5)}};
}

vello_cpp::Point to_vello_point(const SkPoint& p) { return {p.x(), p.y()}; }

vello_cpp::Color to_vello_color(const SkColor4f& color) {
    SkColor c = color.toSkColor();
    return {
            static_cast<uint8_t>(SkColorGetR(c)),
            static_cast<uint8_t>(SkColorGetG(c)),
            static_cast<uint8_t>(SkColorGetB(c)),
            static_cast<uint8_t>(SkColorGetA(c)),
    };
}

WorkgroupSize to_wg_size(const vello_cpp::WorkgroupSize& src) {
    return WorkgroupSize(src.x, src.y, src.z);
}

vello_cpp::Fill to_fill_type(SkPathFillType fillType) {
    // Vello does not provide an encoding for inverse fill types. When Skia uses vello to render
    // a coverage mask for an inverse fill, it encodes a regular fill and inverts the coverage value
    // after sampling the mask.
    switch (fillType) {
        case SkPathFillType::kWinding:
        case SkPathFillType::kInverseWinding:
            return vello_cpp::Fill::NonZero;
        case SkPathFillType::kEvenOdd:
        case SkPathFillType::kInverseEvenOdd:
            return vello_cpp::Fill::EvenOdd;
    }
    return vello_cpp::Fill::NonZero;
}

vello_cpp::CapStyle to_cap_style(SkPaint::Cap cap) {
    switch (cap) {
        case SkPaint::Cap::kButt_Cap:
            return vello_cpp::CapStyle::Butt;
        case SkPaint::Cap::kRound_Cap:
            return vello_cpp::CapStyle::Round;
        case SkPaint::Cap::kSquare_Cap:
            return vello_cpp::CapStyle::Square;
    }
    SkUNREACHABLE;
}

vello_cpp::JoinStyle to_join_style(SkPaint::Join join) {
    switch (join) {
        case SkPaint::Join::kMiter_Join:
            return vello_cpp::JoinStyle::Miter;
        case SkPaint::Join::kBevel_Join:
            return vello_cpp::JoinStyle::Bevel;
        case SkPaint::Join::kRound_Join:
            return vello_cpp::JoinStyle::Round;
    }
    SkUNREACHABLE;
}

vello_cpp::Stroke to_stroke(const SkStrokeRec& style) {
    return vello_cpp::Stroke{
            /*width=*/style.getWidth(),
            /*miter_limit=*/style.getMiter(),
            /*cap*/ to_cap_style(style.getCap()),
            /*join*/ to_join_style(style.getJoin()),
    };
}

class PathIter : public vello_cpp::PathIterator {
public:
    PathIter(const SkPath& path, const Transform& t)
            : fIterate(path), fIter(fIterate.begin()), fTransform(t) {}

    bool next_element(vello_cpp::PathElement* outElem) override {
        if (fConicQuadIdx < fConicConverter.countQuads()) {
            SkASSERT(fConicQuads != nullptr);
            outElem->verb = vello_cpp::PathVerb::QuadTo;
            int pointIdx = fConicQuadIdx * 2;
            outElem->points[0] = to_vello_point(fConicQuads[pointIdx]);
            outElem->points[1] = to_vello_point(fConicQuads[pointIdx + 1]);
            outElem->points[2] = to_vello_point(fConicQuads[pointIdx + 2]);
            fConicQuadIdx++;
            return true;
        }

        if (fIter == fIterate.end()) {
            return false;
        }

        SkASSERT(outElem);
        auto [verb, points, weights] = *fIter;
        fIter++;

        switch (verb) {
            case SkPathVerb::kMove:
                outElem->verb = vello_cpp::PathVerb::MoveTo;
                outElem->points[0] = to_vello_point(points[0]);
                break;
            case SkPathVerb::kLine:
                outElem->verb = vello_cpp::PathVerb::LineTo;
                outElem->points[0] = to_vello_point(points[0]);
                outElem->points[1] = to_vello_point(points[1]);
                break;
            case SkPathVerb::kConic:
                // The vello encoding API doesn't handle conic sections. Approximate it with
                // quadratic Béziers.
                SkASSERT(fConicQuadIdx >= fConicConverter.countQuads());  // No other conic->quad
                                                                          // conversions should be
                                                                          // in progress
                fConicQuads = fConicConverter.computeQuads(
                        points, *weights, 0.25 / fTransform.maxScaleFactor());
                outElem->verb = vello_cpp::PathVerb::QuadTo;
                outElem->points[0] = to_vello_point(fConicQuads[0]);
                outElem->points[1] = to_vello_point(fConicQuads[1]);
                outElem->points[2] = to_vello_point(fConicQuads[2]);

                // The next call to `next_element` will yield the next quad in the list (at index 1)
                // if `fConicConverter` contains more than 1 quad.
                fConicQuadIdx = 1;
                break;
            case SkPathVerb::kQuad:
                outElem->verb = vello_cpp::PathVerb::QuadTo;
                outElem->points[0] = to_vello_point(points[0]);
                outElem->points[1] = to_vello_point(points[1]);
                outElem->points[2] = to_vello_point(points[2]);
                break;
            case SkPathVerb::kCubic:
                outElem->verb = vello_cpp::PathVerb::CurveTo;
                outElem->points[0] = to_vello_point(points[0]);
                outElem->points[1] = to_vello_point(points[1]);
                outElem->points[2] = to_vello_point(points[2]);
                outElem->points[3] = to_vello_point(points[3]);
                break;
            case SkPathVerb::kClose:
                outElem->verb = vello_cpp::PathVerb::Close;
                break;
        }

        return true;
    }

private:
    SkPathPriv::Iterate fIterate;
    SkPathPriv::RangeIter fIter;

    // Variables used to track conic to quadratic spline conversion. `fTransform` is used to
    // determine the subpixel error tolerance in device coordinate space.
    const Transform& fTransform;
    SkAutoConicToQuads fConicConverter;
    const SkPoint* fConicQuads = nullptr;
    int fConicQuadIdx = 0;
};

}  // namespace

VelloScene::VelloScene() : fEncoding(vello_cpp::new_encoding()) {}

void VelloScene::reset() {
    fEncoding->reset();
}

void VelloScene::solidFill(const SkPath& shape,
                           const SkColor4f& fillColor,
                           const SkPathFillType fillType,
                           const Transform& t) {
    PathIter iter(shape, t);
    fEncoding->fill(to_fill_type(fillType),
                    to_vello_affine(t),
                    {vello_cpp::BrushKind::Solid, {to_vello_color(fillColor)}},
                    iter);
}

void VelloScene::solidStroke(const SkPath& shape,
                             const SkColor4f& fillColor,
                             const SkStrokeRec& style,
                             const Transform& t) {
    // TODO: Obtain dashing pattern here and let Vello handle dashing on the CPU while
    // encoding the path?
    PathIter iter(shape, t);
    vello_cpp::Brush brush{vello_cpp::BrushKind::Solid, {to_vello_color(fillColor)}};
    fEncoding->stroke(to_stroke(style), to_vello_affine(t), brush, iter);
}

void VelloScene::pushClipLayer(const SkPath& shape, const Transform& t) {
    PathIter iter(shape, t);
    fEncoding->begin_clip(to_vello_affine(t), iter);
    SkDEBUGCODE(fLayers++;)
}

void VelloScene::popClipLayer() {
    SkASSERT(fLayers > 0);
    fEncoding->end_clip();
    SkDEBUGCODE(fLayers--;)
}

void VelloScene::append(const VelloScene& other) {
    fEncoding->append(*other.fEncoding);
}

VelloRenderer::VelloRenderer(const Caps* caps) {
    if (ComputeShaderCoverageMaskTargetFormat(caps) == kAlpha_8_SkColorType) {
        fFineArea = std::make_unique<VelloFineAreaAlpha8Step>();
        fFineMsaa16 = std::make_unique<VelloFineMsaa16Alpha8Step>();
        fFineMsaa8 = std::make_unique<VelloFineMsaa8Alpha8Step>();
    } else {
        fFineArea = std::make_unique<VelloFineAreaStep>();
        fFineMsaa16 = std::make_unique<VelloFineMsaa16Step>();
        fFineMsaa8 = std::make_unique<VelloFineMsaa8Step>();
    }
}

VelloRenderer::~VelloRenderer() = default;

std::unique_ptr<DispatchGroup> VelloRenderer::renderScene(const RenderParams& params,
                                                          const VelloScene& scene,
                                                          sk_sp<TextureProxy> target,
                                                          Recorder* recorder) const {
    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
    SkASSERT(target);

    if (scene.fEncoding->is_empty()) {
        return nullptr;
    }

    if (params.fWidth == 0 || params.fHeight == 0) {
        return nullptr;
    }

    // TODO: validate that the pixel format matches the pipeline layout.
    // Clamp the draw region to the target texture dimensions.
    const SkISize dims = target->dimensions();
    if (dims.isEmpty() || dims.fWidth < 0 || dims.fHeight < 0) {
        SKGPU_LOG_W("VelloRenderer: cannot render to an empty target");
        return nullptr;
    }

    SkASSERT(scene.fLayers == 0);  // Begin/end clips must be matched.
    auto config = scene.fEncoding->prepare_render(
            std::min(params.fWidth, static_cast<uint32_t>(dims.fWidth)),
            std::min(params.fHeight, static_cast<uint32_t>(dims.fHeight)),
            to_vello_color(params.fBaseColor));
    auto dispatchInfo = config->workgroup_counts();
    auto bufferSizes = config->buffer_sizes();

    DispatchGroup::Builder builder(recorder);

    // In total there are 25 resources that are used across the full pipeline stages. The sizes of
    // these resources depend on the encoded scene. We allocate all of them and assign them
    // directly to the builder here instead of delegating the logic to the ComputeSteps.
    DrawBufferManager* bufMgr = recorder->priv().drawBufferManager();

    // TODO(b/285189802): The default sizes for the bump buffers (~97MB) exceed Graphite's resource
    // budget if multiple passes are necessary per frame (250MB, see ResouceCache.h). We apply a
    // crude size reduction here which seems to be enough for a 4k x 4k atlas render for the GMs
    // that we have tested. The numbers below are able to render GM_longpathdash with CPU-side
    // stroke expansion.
    //
    // We need to come up with a better approach to accurately predict the sizes for these buffers
    // based on the scene encoding and our resource budget. It should be possible to build a
    // conservative estimate using the total number of path verbs, some heuristic based on the verb
    // and the path's transform, and the total number of tiles.
    //
    // The following numbers amount to ~48MB
    const size_t lines_size = bufferSizes.lines;
    const size_t bin_data_size = bufferSizes.bin_data;
    const size_t tiles_size = bufferSizes.tiles;
    const size_t segments_size = bufferSizes.segments;
    const size_t seg_counts_size = bufferSizes.seg_counts;
    const size_t ptcl_size = bufferSizes.ptcl;

    // See the comments in VelloComputeSteps.h for an explanation of the logic here.

    {
        size_t uboSize = config->config_uniform_buffer_size();
        auto [uboWriter, configBuf, _] = bufMgr->getMappedUniformBuffer(uboSize, /*stride=*/1);
        if (!uboWriter ||
            !config->write_config_uniform_buffer(to_slice(uboWriter.slice(uboSize)))) {
            return nullptr;
        }
        builder.assignSharedBuffer(configBuf, kVelloSlot_ConfigUniform);
    }

    {
        size_t sceneSize = config->scene_buffer_size();
        auto [sceneWriter, sceneBuf, _] = bufMgr->getMappedStorageBuffer(sceneSize, /*stride=*/1);
        if (!sceneWriter || !config->write_scene_buffer(to_slice(sceneWriter.slice(sceneSize)))) {
            return nullptr;
        }
        builder.assignSharedBuffer(sceneBuf, kVelloSlot_Scene);
    }

    // Buffers get cleared ahead of the entire DispatchGroup. Allocate the bump buffer early to
    // avoid a potentially recycled (and prematurely cleared) scratch buffer.
    BufferSubAllocator bump = bufMgr->getScratchStorage(bufferSizes.bump_alloc);
    builder.assignSharedBuffer(new_scratch_slice(bump), kVelloSlot_BumpAlloc, ClearBuffer::kYes);

    // path_reduce
    BufferSubAllocator tagmonoids = bufMgr->getScratchStorage(bufferSizes.path_monoids);
    {
        // This can be immediately returned after input processing.
        BufferSubAllocator pathtagReduceOutput =
                bufMgr->getScratchStorage(bufferSizes.path_reduced);
        builder.assignSharedBuffer(new_scratch_slice(pathtagReduceOutput),
                                   kVelloSlot_PathtagReduceOutput);
        builder.assignSharedBuffer(new_scratch_slice(tagmonoids), kVelloSlot_TagMonoid);
        builder.appendStep(&fPathtagReduce, to_wg_size(dispatchInfo.path_reduce));

        // If the input is too large to be fully processed by a single workgroup then a second
        // reduce step and two scan steps are necessary. Otherwise one reduce+scan pair is
        // sufficient.
        //
        // In either case, the result is `tagmonoids`.
        if (dispatchInfo.use_large_path_scan) {
            BufferSubAllocator reduced2 = bufMgr->getScratchStorage(bufferSizes.path_reduced2);
            BufferSubAllocator reducedScan =
                    bufMgr->getScratchStorage(bufferSizes.path_reduced_scan);

            builder.assignSharedBuffer(new_scratch_slice(reduced2),
                                       kVelloSlot_LargePathtagReduceSecondPassOutput);
            builder.assignSharedBuffer(new_scratch_slice(reducedScan),
                                       kVelloSlot_LargePathtagScanFirstPassOutput);

            builder.appendStep(&fPathtagReduce2, to_wg_size(dispatchInfo.path_reduce2));
            builder.appendStep(&fPathtagScan1, to_wg_size(dispatchInfo.path_scan1));
            builder.appendStep(&fPathtagScanLarge, to_wg_size(dispatchInfo.path_scan));
        } else {
            builder.appendStep(&fPathtagScanSmall, to_wg_size(dispatchInfo.path_scan));
        }
    }

    // bbox_clear
    BufferSubAllocator pathBboxes = bufMgr->getScratchStorage(bufferSizes.path_bboxes);
    builder.assignSharedBuffer(new_scratch_slice(pathBboxes), kVelloSlot_PathBBoxes);
    builder.appendStep(&fBboxClear, to_wg_size(dispatchInfo.bbox_clear));

    // flatten
    BufferSubAllocator lines = bufMgr->getScratchStorage(lines_size);
    builder.assignSharedBuffer(new_scratch_slice(lines), kVelloSlot_Lines);
    builder.appendStep(&fFlatten, to_wg_size(dispatchInfo.flatten));

    tagmonoids.reset();

    // draw_reduce
    BufferSubAllocator drawReduced = bufMgr->getScratchStorage(bufferSizes.draw_reduced);
    builder.assignSharedBuffer(new_scratch_slice(drawReduced), kVelloSlot_DrawReduceOutput);
    builder.appendStep(&fDrawReduce, to_wg_size(dispatchInfo.draw_reduce));

    // draw_leaf
    BufferSubAllocator drawMonoids = bufMgr->getScratchStorage(bufferSizes.draw_monoids);
    BufferSubAllocator binData = bufMgr->getScratchStorage(bin_data_size);
    // A clip input buffer must still get bound even if the encoding doesn't contain any clips
    BufferSubAllocator clipInput = bufMgr->getScratchStorage(bufferSizes.clip_inps);
    builder.assignSharedBuffer(new_scratch_slice(drawMonoids), kVelloSlot_DrawMonoid);
    builder.assignSharedBuffer(new_scratch_slice(binData), kVelloSlot_InfoBinData);
    builder.assignSharedBuffer(new_scratch_slice(clipInput), kVelloSlot_ClipInput);
    builder.appendStep(&fDrawLeaf, to_wg_size(dispatchInfo.draw_leaf));

    drawReduced.reset();

    // clip_reduce, clip_leaf
    // The clip bbox buffer is always an input to the binning stage, even when the encoding doesn't
    // contain any clips
    BufferSubAllocator clipBboxes = bufMgr->getScratchStorage(bufferSizes.clip_bboxes);
    builder.assignSharedBuffer(new_scratch_slice(clipBboxes), kVelloSlot_ClipBBoxes);
    WorkgroupSize clipReduceWgCount = to_wg_size(dispatchInfo.clip_reduce);
    WorkgroupSize clipLeafWgCount = to_wg_size(dispatchInfo.clip_leaf);
    bool doClipReduce = clipReduceWgCount.scalarSize() > 0u;
    bool doClipLeaf = clipLeafWgCount.scalarSize() > 0u;
    if (doClipReduce || doClipLeaf) {
        BufferSubAllocator clipBic = bufMgr->getScratchStorage(bufferSizes.clip_bics);
        BufferSubAllocator clipEls = bufMgr->getScratchStorage(bufferSizes.clip_els);
        builder.assignSharedBuffer(new_scratch_slice(clipBic), kVelloSlot_ClipBicyclic);
        builder.assignSharedBuffer(new_scratch_slice(clipEls), kVelloSlot_ClipElement);
        if (doClipReduce) {
            builder.appendStep(&fClipReduce, clipReduceWgCount);
        }
        if (doClipLeaf) {
            builder.appendStep(&fClipLeaf, clipLeafWgCount);
        }
    }

    clipInput.reset();

    // binning
    BufferSubAllocator drawBboxes = bufMgr->getScratchStorage(bufferSizes.draw_bboxes);
    BufferSubAllocator binHeaders = bufMgr->getScratchStorage(bufferSizes.bin_headers);
    builder.assignSharedBuffer(new_scratch_slice(drawBboxes), kVelloSlot_DrawBBoxes);
    builder.assignSharedBuffer(new_scratch_slice(binHeaders), kVelloSlot_BinHeader);
    builder.appendStep(&fBinning, to_wg_size(dispatchInfo.binning));

    pathBboxes.reset();
    clipBboxes.reset();

    // tile_alloc
    BufferSubAllocator paths = bufMgr->getScratchStorage(bufferSizes.paths);
    BufferSubAllocator tiles = bufMgr->getScratchStorage(tiles_size);
    builder.assignSharedBuffer(new_scratch_slice(paths), kVelloSlot_Path);
    builder.assignSharedBuffer(new_scratch_slice(tiles), kVelloSlot_Tile);
    builder.appendStep(&fTileAlloc, to_wg_size(dispatchInfo.tile_alloc));

    drawBboxes.reset();

    // path_count_setup
    auto indirectCountBuffer = new_indirect_slice(bufMgr, bufferSizes.indirect_count);
    builder.assignSharedBuffer(indirectCountBuffer, kVelloSlot_IndirectCount);
    builder.appendStep(&fPathCountSetup, to_wg_size(dispatchInfo.path_count_setup));

    // Rasterization stage scratch buffers.
    BufferSubAllocator seg_counts = bufMgr->getScratchStorage(seg_counts_size);
    BufferSubAllocator segments = bufMgr->getScratchStorage(segments_size);
    BufferSubAllocator ptcl = bufMgr->getScratchStorage(ptcl_size);

    // path_count
    builder.assignSharedBuffer(new_scratch_slice(seg_counts), kVelloSlot_SegmentCounts);
    builder.appendStepIndirect(&fPathCount, indirectCountBuffer);

    // backdrop
    builder.appendStep(&fBackdrop, to_wg_size(dispatchInfo.backdrop));

    // coarse
    builder.assignSharedBuffer(new_scratch_slice(ptcl), kVelloSlot_PTCL);
    builder.appendStep(&fCoarse, to_wg_size(dispatchInfo.coarse));

    // path_tiling_setup
    builder.appendStep(&fPathTilingSetup, to_wg_size(dispatchInfo.path_tiling_setup));

    // path_tiling
    builder.assignSharedBuffer(new_scratch_slice(segments), kVelloSlot_Segments);
    builder.appendStepIndirect(&fPathTiling, indirectCountBuffer);

    // fine
    builder.assignSharedTexture(std::move(target), kVelloSlot_OutputImage);
    const ComputeStep* fineVariant = nullptr;
    switch (params.fAaConfig) {
        case VelloAaConfig::kAnalyticArea:
            fineVariant = fFineArea.get();
            break;
        case VelloAaConfig::kMSAA16:
            fineVariant = fFineMsaa16.get();
            break;
        case VelloAaConfig::kMSAA8:
            fineVariant = fFineMsaa8.get();
            break;
    }
    SkASSERT(fineVariant != nullptr);
    builder.appendStep(fineVariant, to_wg_size(dispatchInfo.fine));

    return builder.finalize();
}

}  // namespace skgpu::graphite
