/*
 * Copyright 2021 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"

#include "include/gpu/graphite/Context.h"
#include "include/gpu/graphite/TextureInfo.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/ContextPriv.h"
#include "src/gpu/graphite/PipelineData.h"
#include "src/gpu/graphite/TextureProxy.h"

using namespace skgpu::graphite;

DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(PipelineDataCacheTest, reporter, context,
                                   CtsEnforcement::kApiLevel_202404) {
    const Caps* caps = context->priv().caps();
    ResourceProvider* resourceProvider = context->priv().resourceProvider();

    // Setup caches
    UniformDataCache uCache;
    TextureDataCache tCache;

    REPORTER_ASSERT(reporter, uCache.count() == 0);
    REPORTER_ASSERT(reporter, tCache.bindingCount() == 0);


    // Create testing textures and uniforms
    [[maybe_unused]] static constexpr Uniform kUniforms[] = {{"data", SkSLType::kFloat4}};
    TextureInfo info = caps->getDefaultSampledTextureInfo(kAlpha_8_SkColorType,
                                                          skgpu::Mipmapped::kNo,
                                                          skgpu::Protected::kNo,
                                                          skgpu::Renderable::kYes);
    REPORTER_ASSERT(reporter, info.isValid());

    sk_sp<TextureProxy> proxyA = TextureProxy::Make(caps,
                                                    resourceProvider,
                                                    SkISize::Make(32, 32),
                                                    info,
                                                    "TestDataProxyA",
                                                    skgpu::Budgeted::kYes);
    sk_sp<TextureProxy> proxyB = TextureProxy::Make(caps,
                                                    resourceProvider,
                                                    SkISize::Make(32, 32),
                                                    info,
                                                    "TestDataProxyB",
                                                    skgpu::Budgeted::kYes);
    REPORTER_ASSERT(reporter, proxyA && proxyB);

    // Block A: Add a new, unique set of uniforms and textures for a render step
    UniformDataCache::Index uID1;
    TextureDataCache::Index tID1;
    {
        PipelineDataGatherer gatherer{Layout::kStd430};
        gatherer.setRenderStepManagerActive(); // Set active manager for render step data

        SkDEBUGCODE(UniformExpectationsValidator uev(&gatherer, kUniforms);)
        gatherer.write(SkV4{1.f, 2.f, 3.f, 4.f});
        gatherer.add(proxyA, {});

        auto [udb, tdb] = gatherer.endRenderStepData(/*performsShading=*/true);

        uID1 = uCache.insert(udb);
        tID1 = tCache.insert(tdb);

        REPORTER_ASSERT(reporter, uCache.count() == 1);
        REPORTER_ASSERT(reporter, tCache.bindingCount() == 1);
        REPORTER_ASSERT(reporter, tCache.uniqueTextureCount() == 1);

        // Verify lookup
        REPORTER_ASSERT(reporter, uCache.lookup(uID1).fCpuData == udb);
        REPORTER_ASSERT(reporter, tCache.lookup(tID1) == tdb);
    }

    // Block B: Add the exact same render step data to test de-duplication
    {
        PipelineDataGatherer gatherer{Layout::kStd430};
        gatherer.setRenderStepManagerActive();

        SkDEBUGCODE(UniformExpectationsValidator uev(&gatherer, kUniforms);)
        gatherer.write(SkV4{1.f, 2.f, 3.f, 4.f}); // Same uniform data
        gatherer.add(proxyA, {});                 // Same texture

        auto [udb, tdb] = gatherer.endRenderStepData(/*performsShading=*/true);

        UniformDataCache::Index uID2 = uCache.insert(udb);
        TextureDataCache::Index tID2 = tCache.insert(tdb);

        REPORTER_ASSERT(reporter, uID2 == uID1); // Index should be the same
        REPORTER_ASSERT(reporter, tID2 == tID1); // Index should be the same

        REPORTER_ASSERT(reporter, uCache.count() == 1);        // Count should NOT increase
        REPORTER_ASSERT(reporter, tCache.bindingCount() == 1); // Count should NOT increase
    }

    // Block C: Add new unique render step uniforms but the same texture
    UniformDataCache::Index uID3;
    {
        PipelineDataGatherer gatherer{Layout::kStd430};
        gatherer.setRenderStepManagerActive();

        SkDEBUGCODE(UniformExpectationsValidator uev(&gatherer, kUniforms);)
        gatherer.write(SkV4{5.f, 6.f, 7.f, 8.f}); // Different uniform data
        gatherer.add(proxyA, {});                 // Same texture

        auto [udb, tdb] = gatherer.endRenderStepData(/*performsShading=*/true);

        uID3 = uCache.insert(udb);
        TextureDataCache::Index tID3 = tCache.insert(tdb);

        REPORTER_ASSERT(reporter, uID3 != uID1); // New unique uniform index
        REPORTER_ASSERT(reporter, tID3 == tID1); // Same texture binding index

        REPORTER_ASSERT(reporter, uCache.count() == 2);        // Uniform count increases
        REPORTER_ASSERT(reporter, tCache.bindingCount() == 1); // Texture count does not
    }

    // Block D: Add the same render step uniforms but a new unique texture
    {
        PipelineDataGatherer gatherer{Layout::kStd430};
        gatherer.setRenderStepManagerActive();

        SkDEBUGCODE(UniformExpectationsValidator uev(&gatherer, kUniforms);)
        gatherer.write(SkV4{1.f, 2.f, 3.f, 4.f}); // Same uniform data as Block A
        gatherer.add(proxyB, {});                 // Different texture

        auto [udb, tdb] = gatherer.endRenderStepData(/*performsShading=*/true);

        UniformDataCache::Index uID4 = uCache.insert(udb);
        TextureDataCache::Index tID4 = tCache.insert(tdb);

        REPORTER_ASSERT(reporter, uID4 == uID1); // Same uniform index
        REPORTER_ASSERT(reporter, tID4 != tID1); // New unique texture index

        REPORTER_ASSERT(reporter, uCache.count() == 2);        // Uniform count does not increase
        REPORTER_ASSERT(reporter, tCache.bindingCount() == 2); // Texture count increases
        REPORTER_ASSERT(reporter, tCache.uniqueTextureCount() == 2);
    }

    // Block E: Add a unique paint uniform.
    UniformDataCache::Index uID5;
    {
        PipelineDataGatherer gatherer{Layout::kStd430};
        // Starts in paint mode by default, no state change needed.
        SkDEBUGCODE(UniformExpectationsValidator uev(&gatherer, kUniforms);)
        gatherer.write(SkV4{10.f, 20.f, 30.f, 40.f}); // New unique paint uniform data

        UniformDataBlock udb = gatherer.endPaintData();
        uID5 = uCache.insert(udb);

        REPORTER_ASSERT(reporter, uID5 != uID1 && uID5 != uID3); // New unique uniform index
        REPORTER_ASSERT(reporter, uCache.count() == 3);          // Uniform count increases
    }

    // Block F: Add the same paint uniform to test de-duplication.
    {
        PipelineDataGatherer gatherer{Layout::kStd430};
        SkDEBUGCODE(UniformExpectationsValidator uev(&gatherer, kUniforms);)
        gatherer.write(SkV4{10.f, 20.f, 30.f, 40.f}); // Same paint uniform data as Block E

        UniformDataBlock udb = gatherer.endPaintData();
        UniformDataCache::Index uID6 = uCache.insert(udb);

        REPORTER_ASSERT(reporter, uID6 == uID5);        // Index should be the same
        REPORTER_ASSERT(reporter, uCache.count() == 3); // Count should NOT increase
    }

    // Block G: Test paint and render step uniforms together.
    {
        PipelineDataGatherer gatherer{Layout::kStd430};

        // 1. Add paint data
        {
            SkDEBUGCODE(UniformExpectationsValidator paintUev(&gatherer, kUniforms);)
            gatherer.write(SkV4{10.f, 20.f, 30.f, 40.f});   // Same paint uniform as Block E
            gatherer.add(proxyA, {});

            UniformDataBlock paintUdb = gatherer.endPaintData();
            UniformDataCache::Index paintUID = uCache.insert(paintUdb);

            REPORTER_ASSERT(reporter, paintUID == uID5);    // Should de-duplicate with Block E
            REPORTER_ASSERT(reporter, uCache.count() == 3); // Count should NOT increase
        }

        // 2. Add render step data
        {
            gatherer.setRenderStepManagerActive();    // Switch to render step mode
            SkDEBUGCODE(UniformExpectationsValidator rsUev(&gatherer, kUniforms);)
            gatherer.write(SkV4{1.f, 2.f, 3.f, 4.f}); // Same render step uniform as Block A
            gatherer.add(proxyB, {});

            auto [rsUdb, combinedTdb] = gatherer.endRenderStepData(/*performsShading=*/true);

            UniformDataCache::Index rsUID = uCache.insert(rsUdb);
            REPORTER_ASSERT(reporter, rsUID == uID1);       // Should de-duplicate with Block A
            REPORTER_ASSERT(reporter, uCache.count() == 3); // Count should NOT increase

            // 3. Check combined texture data
            REPORTER_ASSERT(reporter, combinedTdb.numTextures() == 2);
            TextureDataCache::Index combinedTID = tCache.insert(combinedTdb);

            REPORTER_ASSERT(reporter, combinedTID != tID1);              // New binding
            REPORTER_ASSERT(reporter, tCache.bindingCount() == 3);       // Count increases
            REPORTER_ASSERT(reporter, tCache.uniqueTextureCount() == 2); // Still 2 unique proxies
        }
    }
}
