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

#include "tests/Test.h"

#if defined(SK_GRAPHITE)

#include "include/core/SkCanvas.h"
#include "include/core/SkPaint.h"
#include "include/core/SkTextBlob.h"
#include "include/effects/SkGradientShader.h"
#include "include/gpu/graphite/PrecompileContext.h"
#include "include/gpu/graphite/Surface.h"
#include "include/gpu/graphite/precompile/PaintOptions.h"
#include "include/gpu/graphite/precompile/Precompile.h"
#include "include/gpu/graphite/precompile/PrecompileShader.h"
#include "src/gpu/graphite/ContextPriv.h"
#include "src/gpu/graphite/GraphicsPipelineDesc.h"
#include "src/gpu/graphite/RenderPassDesc.h"
#include "src/gpu/graphite/ResourceProvider.h"
#include "tools/fonts/FontToolUtils.h"
#include "tools/graphite/UniqueKeyUtils.h"

#include <algorithm>
#include <random>
#include <thread>

using namespace::skgpu::graphite;

namespace {

static constexpr int kMaxNumStops = 9;
static constexpr SkColor gColors[kMaxNumStops] = {
        SK_ColorRED,
        SK_ColorGREEN,
        SK_ColorBLUE,
        SK_ColorCYAN,
        SK_ColorMAGENTA,
        SK_ColorYELLOW,
        SK_ColorBLACK,
        SK_ColorDKGRAY,
        SK_ColorLTGRAY,
};
static constexpr SkPoint gPts[kMaxNumStops] = {
        { -100.0f, -100.0f },
        { -50.0f, -50.0f },
        { -25.0f, -25.0f },
        { -12.5f, -12.5f },
        { 0.0f, 0.0f },
        { 12.5f, 12.5f },
        { 25.0f, 25.0f },
        { 50.0f, 50.0f },
        { 100.0f, 100.0f }
};
static constexpr float gOffsets[kMaxNumStops] =
            { 0.0f, 0.125f, 0.25f, 0.375f, 0.5f, 0.625f, 0.75f, 0.875f, 1.0f };

std::pair<SkPaint, PaintOptions> linear(int numStops) {
    SkASSERT(numStops <= kMaxNumStops);

    PaintOptions paintOptions;
    paintOptions.setShaders({ PrecompileShaders::LinearGradient() });
    paintOptions.setBlendModes({ SkBlendMode::kSrcOver });

    SkPaint paint;
    paint.setShader(SkGradientShader::MakeLinear(gPts,
                                                 gColors, gOffsets, numStops,
                                                 SkTileMode::kClamp));
    paint.setBlendMode(SkBlendMode::kSrcOver);

    return { paint, paintOptions };
}

std::pair<SkPaint, PaintOptions> radial(int numStops) {
    SkASSERT(numStops <= kMaxNumStops);

    PaintOptions paintOptions;
    paintOptions.setShaders({ PrecompileShaders::RadialGradient() });
    paintOptions.setBlendModes({ SkBlendMode::kSrcOver });

    SkPaint paint;
    paint.setShader(SkGradientShader::MakeRadial(/* center= */ {0, 0}, /* radius= */ 100,
                                                 gColors, gOffsets, numStops,
                                                 SkTileMode::kClamp));
    paint.setBlendMode(SkBlendMode::kSrcOver);

    return { paint, paintOptions };
}

std::pair<SkPaint, PaintOptions> sweep(int numStops) {
    SkASSERT(numStops <= kMaxNumStops);

    PaintOptions paintOptions;
    paintOptions.setShaders({ PrecompileShaders::SweepGradient() });
    paintOptions.setBlendModes({ SkBlendMode::kSrcOver });

    SkPaint paint;
    paint.setShader(SkGradientShader::MakeSweep(/* cx= */ 0, /* cy= */ 0,
                                                gColors, gOffsets, numStops,
                                                SkTileMode::kClamp,
                                                /* startAngle= */ 0, /* endAngle= */ 359,
                                                /* flags= */ 0, /* localMatrix= */ nullptr));
    paint.setBlendMode(SkBlendMode::kSrcOver);

    return { paint, paintOptions };
}

std::pair<SkPaint, PaintOptions> conical(int numStops) {
    SkASSERT(numStops <= kMaxNumStops);

    PaintOptions paintOptions;
    paintOptions.setShaders({ PrecompileShaders::TwoPointConicalGradient() });
    paintOptions.setBlendModes({ SkBlendMode::kSrcOver });

    SkPaint paint;
    paint.setShader(SkGradientShader::MakeTwoPointConical(/* start= */ {100, 100},
                                                          /* startRadius= */ 100,
                                                          /* end= */ {-100, -100},
                                                          /* endRadius= */ 100,
                                                          gColors, gOffsets, numStops,
                                                          SkTileMode::kClamp));
    paint.setBlendMode(SkBlendMode::kSrcOver);

    return { paint, paintOptions };
}

// The 12 comes from 4 types of gradient times 3 combinations (i.e., 4,8,N) for each one.
static constexpr int kNumDiffPipelines = 12;

typedef std::pair<SkPaint, PaintOptions> (*GradientCreationFunc)(int numStops);

struct Combo {
    GradientCreationFunc fCreateOptionsMtd;
    int fNumStops;
};

void precompile_gradients(std::unique_ptr<PrecompileContext> precompileContext,
                          bool permute,
                          skiatest::Reporter* /* reporter */,
                          int /* threadID */) {
    std::array<Combo, 4> combos;

    // numStops doesn't influence the paintOptions
    combos[0] = { linear,  /* fNumStops= */ 2 };
    combos[1] = { radial,  /* fNumStops= */ 2 };
    combos[2] = { sweep,   /* fNumStops= */ 2 };
    combos[3] = { conical, /* fNumStops= */ 2 };

    if (permute) {
        std::random_device rd;
        std::mt19937 g(rd());

        std::shuffle(combos.begin(), combos.end(), g);
    }

    const RenderPassProperties kProps = { DepthStencilFlags::kDepth,
                                          kBGRA_8888_SkColorType,
                                          /* dstColorSpace= */ nullptr,
                                          /* requiresMSAA= */ false };

    for (auto c : combos) {
        auto [_, paintOptions] = c.fCreateOptionsMtd(c.fNumStops);
        Precompile(precompileContext.get(),
                   paintOptions,
                   DrawTypeFlags::kBitmapText_Mask,
                   { &kProps, 1 });
    }

    precompileContext.reset();
}

void purge_on_thread(std::unique_ptr<PrecompileContext> precompileContext,
                     std::atomic_bool* keepLooping,
                     skiatest::Reporter* /* reporter */,
                     int /* threadID */) {
    const auto kSleepDuration = std::chrono::milliseconds(1);

    while (*keepLooping) {
        std::this_thread::sleep_for(kSleepDuration);

        precompileContext->purgePipelinesNotUsedInMs(kSleepDuration);
    }

    precompileContext.reset();
}

// A simple helper to call Context::insertRecording on the Recordings generated on the
// recorder threads. It collects (and keeps ownership) of all the generated Recordings.
class Listener : public SkRefCnt {
public:
    Listener(int numSenders) : fNumActiveSenders(numSenders) {}

    void addRecording(std::unique_ptr<Recording> recording) SK_EXCLUDES(fLock) {
        {
            SkAutoMutexExclusive lock(fLock);
            fRecordings.push_back(std::move(recording));
        }

        fWorkAvailable.signal(1);
    }

    void deregister() SK_EXCLUDES(fLock) {
        {
            SkAutoMutexExclusive lock(fLock);
            fNumActiveSenders--;
        }

        fWorkAvailable.signal(1);
    }

    void insertRecordings(Context* context) {
        do {
            fWorkAvailable.wait();
        } while (this->insertRecording(context));
    }

private:
    // This entry point is run in a loop waiting on the 'fWorkAvailable' semaphore until there
    // are no senders remaining (at which point it returns false) c.f. 'insertRecordings'.
    bool insertRecording(Context* context) SK_EXCLUDES(fLock) {
        Recording* recording = nullptr;
        int numSendersLeft;

        {
            SkAutoMutexExclusive lock(fLock);

            numSendersLeft = fNumActiveSenders;

            SkASSERT(fRecordings.size() >= fCurHandled);
            if (fRecordings.size() > fCurHandled) {
                recording = fRecordings[fCurHandled++].get();
            }
        }

        if (recording) {
            context->insertRecording({recording});
            return true;  // continue looping
        }

        return SkToBool(numSendersLeft); // continue looping if there are still active senders
    }

    SkMutex fLock;
    SkSemaphore fWorkAvailable;

    skia_private::TArray<std::unique_ptr<Recording>> fRecordings SK_GUARDED_BY(fLock);
    int fCurHandled SK_GUARDED_BY(fLock) = 0;
    int fNumActiveSenders SK_GUARDED_BY(fLock);
};

void compile_gradients(std::unique_ptr<Recorder> recorder,
                       sk_sp<Listener> listener,
                       bool permute,
                       skiatest::Reporter* /* reporter */,
                       int /* threadID */) {
    std::array<Combo, kNumDiffPipelines> combos;

    int i = 0;
    for (auto createOptionsMtd : { linear, radial, sweep, conical }) {
        for (int numStops: { 2, 7, kMaxNumStops }) {
            combos[i++] = { createOptionsMtd, numStops };
        }
    }

    if (permute) {
        std::random_device rd;
        std::mt19937 g(rd());

        std::shuffle(combos.begin(), combos.end(), g);
    }

    SkFont font(ToolUtils::DefaultPortableTypeface(), /* size= */ 16);

    const char text[] = "hambur1";
    sk_sp<SkTextBlob> blob = SkTextBlob::MakeFromText(text, strlen(text), font);

    SkImageInfo ii = SkImageInfo::Make(16, 16,
                                       kBGRA_8888_SkColorType,
                                       kPremul_SkAlphaType);

    sk_sp<SkSurface> surf = SkSurfaces::RenderTarget(recorder.get(), ii,
                                                     skgpu::Mipmapped::kNo,
                                                     /* surfaceProps= */ nullptr);
    SkCanvas* canvas = surf->getCanvas();

    for (auto c : combos) {
        auto [paint, _] = c.fCreateOptionsMtd(c.fNumStops);

        canvas->drawTextBlob(blob, 0, 16, paint);

        // This will trigger pipeline creation via TaskList::prepareResources
        std::unique_ptr<skgpu::graphite::Recording> recording = recorder->snap();

        listener->addRecording(std::move(recording));
    }

    listener->deregister();
}

void run_test(Context* context,
              skiatest::Reporter* reporter,
              int numPurgingThreads,
              int numRecordingThreads,
              int numPrecompileThreads,
              bool permute) {
    const int totNumThreads = numPurgingThreads + numRecordingThreads + numPrecompileThreads;

    sk_sp<Listener> listener;
    if (numRecordingThreads) {
        listener = sk_make_sp<Listener>(numRecordingThreads);
    }

    std::atomic_bool keepPurging = true; // controls the looping in the purging thread(s)

    std::vector<std::thread> threads;
    threads.reserve(totNumThreads);

    int threadID = 0;
    for (int i = 0; i < numPurgingThreads; ++i, ++threadID) {
        std::unique_ptr<PrecompileContext> precompileContext = context->makePrecompileContext();

        threads.push_back(std::thread(purge_on_thread,
                                      std::move(precompileContext),
                                      &keepPurging,
                                      reporter,
                                      threadID));
    }
    for (int i = 0; i < numRecordingThreads; ++i, ++threadID) {
        std::unique_ptr<Recorder> recorder = context->makeRecorder();

        threads.push_back(std::thread(compile_gradients,
                                      std::move(recorder),
                                      listener,
                                      permute,
                                      reporter,
                                      threadID));
    }
    for (int i = 0; i < numPrecompileThreads; ++i, ++threadID) {
        std::unique_ptr<PrecompileContext> precompileContext = context->makePrecompileContext();

        threads.push_back(std::thread(precompile_gradients,
                                      std::move(precompileContext),
                                      permute,
                                      reporter,
                                      threadID));
    }

    // Process the work generated by the recording threads
    if (listener) {
        listener->insertRecordings(context);
    }

    keepPurging = false; // stop the loops in the purging thread(s)

    for (auto& thread : threads) {
        if (thread.joinable()) {
            thread.join();
        }
    }

    context->submit(SyncToCpu::kYes);
}

[[maybe_unused]] void dump_stats(skgpu::BackendApi api, const GlobalCache::PipelineStats& stats) {
    SkDebugf("%s ------------------------------------------------------------------------------\n"
             "CacheHits: %d\n"
             "CacheMisses: %d\n"
             "CacheAdditions: %d\n"
             "Races: %d\n"
             "Purges: %d\n",
             BackendApiToStr(api),
             stats.fGraphicsCacheHits,
             stats.fGraphicsCacheMisses,
             stats.fGraphicsCacheAdditions,
             stats.fGraphicsRaces,
             stats.fGraphicsPurges);
}

} // anonymous namespace

// This test precompiles all four flavors of gradient sequentially but on multiple
// threads with the goal of creating cache races.
DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(ThreadedPipelinePrecompileTest,
                                   reporter,
                                   context,
                                   CtsEnforcement::kNever) {
    constexpr int kNumPurgingThreads = 0;
    constexpr int kNumRecordingThreads = 0;
    constexpr int kNumPrecompileThreads = 4;
    constexpr bool kDontPermute = false;

    run_test(context, reporter, kNumPurgingThreads, kNumRecordingThreads, kNumPrecompileThreads,
             kDontPermute);

    const GlobalCache::PipelineStats stats = context->priv().globalCache()->getStats();

    // The 48 comes from:
    //     4 gradient flavors (linear, radial, ...) *
    //     3 types of each flavor (4, 8, N) *
    //     4 precompile threads
    REPORTER_ASSERT(reporter, stats.fGraphicsCacheHits + stats.fGraphicsCacheMisses == 48);
    REPORTER_ASSERT(reporter, stats.fGraphicsCacheAdditions == kNumDiffPipelines);
    REPORTER_ASSERT(reporter, stats.fGraphicsRaces > 0);
    REPORTER_ASSERT(reporter, stats.fGraphicsPurges == 0);

    REPORTER_ASSERT(reporter, stats.fGraphicsCacheMisses == stats.fGraphicsCacheAdditions +
                                                            stats.fGraphicsRaces);
}

// This test runs two threads compiling the gradient flavours and two threads
// pre-compiling the gradient flavors. This is to exercise the tracking of the
// various race combinations (i.e., Normal vs Precompile, Normal vs. Normal, etc.).
DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(ThreadedPipelinePrecompileCompileTest,
                                   reporter,
                                   context,
                                   CtsEnforcement::kNever) {
    constexpr int kNumPurgingThreads = 0;
    constexpr int kNumRecordingThreads = 2;
    constexpr int kNumPrecompileThreads = 2;
    constexpr bool kDontPermute = false;

    run_test(context, reporter, kNumPurgingThreads, kNumRecordingThreads, kNumPrecompileThreads,
             kDontPermute);

    const GlobalCache::PipelineStats stats = context->priv().globalCache()->getStats();

    // The 48 comes from:
    //     4 gradient flavors (linear, radial, ...) *
    //     3 types of each flavor (4, 8, N) *
    //     (2 normal-compile threads + 2 pre-compile threads)
    REPORTER_ASSERT(reporter, stats.fGraphicsCacheHits + stats.fGraphicsCacheMisses == 48);
    REPORTER_ASSERT(reporter, stats.fGraphicsCacheAdditions == kNumDiffPipelines);
    REPORTER_ASSERT(reporter, stats.fGraphicsRaces > 0);
    REPORTER_ASSERT(reporter, stats.fGraphicsPurges == 0);

    REPORTER_ASSERT(reporter, stats.fGraphicsCacheMisses == stats.fGraphicsCacheAdditions +
                                                            stats.fGraphicsRaces);
}

// This test compiles the gradient flavors on a thread and then tests out the time-based
// purging.
DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(ThreadedPipelineCompilePurgingTest,
                                   reporter,
                                   context,
                                   CtsEnforcement::kNever) {
    constexpr int kNumPurgingThreads = 0;
    constexpr int kNumRecordingThreads = 1;
    constexpr int kNumPrecompileThreads = 0;
    constexpr bool kDontPermute = false;

    std::unique_ptr<PrecompileContext> precompileContext = context->makePrecompileContext();

    auto begin = std::chrono::steady_clock::now();

    run_test(context, reporter, kNumPurgingThreads, kNumRecordingThreads, kNumPrecompileThreads,
             kDontPermute);

    auto end = std::chrono::steady_clock::now();

    auto deltaMS = std::chrono::duration_cast<std::chrono::milliseconds>(end - begin);

    precompileContext->purgePipelinesNotUsedInMs(2*deltaMS);

    GlobalCache::PipelineStats stats = context->priv().globalCache()->getStats();

    REPORTER_ASSERT(reporter, stats.fGraphicsCacheHits == 0);
    REPORTER_ASSERT(reporter, stats.fGraphicsCacheMisses == kNumDiffPipelines);
    REPORTER_ASSERT(reporter, stats.fGraphicsCacheAdditions == kNumDiffPipelines);
    REPORTER_ASSERT(reporter, stats.fGraphicsRaces == 0);
    // Every created Pipeline should've been used since the start of this test
    REPORTER_ASSERT(reporter, stats.fGraphicsPurges == 0, "num purges: %d", stats.fGraphicsPurges);

    //--------------------------------------------------------------------------------------------
    const auto kSleepDuration = std::chrono::milliseconds(1);

    std::this_thread::sleep_for(kSleepDuration);

    precompileContext->purgePipelinesNotUsedInMs(kSleepDuration);

    stats = context->priv().globalCache()->getStats();

    REPORTER_ASSERT(reporter, stats.fGraphicsCacheHits == 0);
    REPORTER_ASSERT(reporter, stats.fGraphicsCacheMisses == kNumDiffPipelines);
    REPORTER_ASSERT(reporter, stats.fGraphicsCacheAdditions == kNumDiffPipelines);
    REPORTER_ASSERT(reporter, stats.fGraphicsRaces == 0);
    // None of the created Pipelines should've been used since we started to sleep - so they
    // all get purged.
    REPORTER_ASSERT(reporter, stats.fGraphicsPurges == kNumDiffPipelines);
}

// This test *precompiles* the gradient flavors on a thread and then tests out the time-based
// purging.
DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(ThreadedPipelinePrecompilePurgingTest,
                                   reporter,
                                   context,
                                   CtsEnforcement::kNever) {
    constexpr int kNumPurgingThreads = 0;
    constexpr int kNumRecordingThreads = 0;
    constexpr int kNumPrecompileThreads = 1;
    constexpr bool kDontPermute = false;

    std::unique_ptr<PrecompileContext> precompileContext = context->makePrecompileContext();

    auto begin = std::chrono::steady_clock::now();

    run_test(context, reporter, kNumPurgingThreads, kNumRecordingThreads, kNumPrecompileThreads,
             kDontPermute);

    auto end = std::chrono::steady_clock::now();

    auto deltaMS = std::chrono::duration_cast<std::chrono::milliseconds>(end - begin);

    precompileContext->purgePipelinesNotUsedInMs(deltaMS);

    GlobalCache::PipelineStats stats = context->priv().globalCache()->getStats();

    REPORTER_ASSERT(reporter, stats.fGraphicsCacheHits == 0);
    REPORTER_ASSERT(reporter, stats.fGraphicsCacheMisses == kNumDiffPipelines);
    REPORTER_ASSERT(reporter, stats.fGraphicsCacheAdditions == kNumDiffPipelines);
    REPORTER_ASSERT(reporter, stats.fGraphicsRaces == 0);
    // Precompilation doesn't count as a use so all the Pipelines will be purged even though
    // they were created w/in 'deltaMS'
    REPORTER_ASSERT(reporter, stats.fGraphicsPurges == kNumDiffPipelines);
}

// This test fires off two compilation threads, two precompilation threads and one
// purging thread. This is intended to stress test the Pipeline cache's thread safety and
// the purging behavior.
DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(ThreadedPipelinePrecompileCompilePurgingTest,
                                   reporter,
                                   context,
                                   CtsEnforcement::kNever) {
    constexpr int kNumPurgingThreads = 1;
    constexpr int kNumRecordingThreads = 2;
    constexpr int kNumPrecompileThreads = 2;
    constexpr bool kPermute = true;

    run_test(context, reporter, kNumPurgingThreads, kNumRecordingThreads, kNumPrecompileThreads,
             kPermute);

    GlobalCache::PipelineStats stats = context->priv().globalCache()->getStats();

    // The 48 comes from:
    //     4 gradient flavors (linear, radial, ...) *
    //     3 types of each flavor (4, 8, N) *
    //     (2 normal-compile threads + 2 pre-compile threads)
    REPORTER_ASSERT(reporter, stats.fGraphicsCacheHits + stats.fGraphicsCacheMisses == 48);
    REPORTER_ASSERT(reporter, stats.fGraphicsCacheMisses == stats.fGraphicsCacheAdditions +
                                                            stats.fGraphicsRaces);
    // Purges can force recreation of a Pipeline
    REPORTER_ASSERT(reporter, stats.fGraphicsCacheAdditions >= kNumDiffPipelines);
    // Given the use of permutations it is possible, though unlikely, that there are
    // no races (particularly on Dawn/Metal).
    //REPORTER_ASSERT(reporter, stats.fGraphicsRaces > 0);
}

#endif // SK_GRAPHITE
