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

#include "GrVkResourceProvider.h"

#include "GrVkGpu.h"
#include "GrProcessor.h"
#include "GrRenderTargetPriv.h" // TODO: remove once refPipelineState gets passed stencil settings.
#include "GrVkPipelineState.h"
#include "GrVkPipelineStateBuilder.h"
#include "SkOpts.h"
#include "glsl/GrGLSLFragmentProcessor.h"
#include "glsl/GrGLSLProgramDataManager.h"

#ifdef GR_PIPELINE_STATE_CACHE_STATS
// Display pipeline state cache usage
static const bool c_DisplayVkPipelineCache{false};
#endif

struct GrVkResourceProvider::PipelineStateCache::Entry {

    Entry() : fPipelineState(nullptr) {}

    static const GrVkPipelineState::Desc& GetKey(const Entry* entry) {
        return entry->fPipelineState->getDesc();
    }

    static uint32_t Hash(const GrVkPipelineState::Desc& key) {
        return key.getChecksum();
    }

    sk_sp<GrVkPipelineState> fPipelineState;

private:
    SK_DECLARE_INTERNAL_LLIST_INTERFACE(Entry);
};

GrVkResourceProvider::PipelineStateCache::PipelineStateCache(GrVkGpu* gpu)
    : fCount(0)
    , fGpu(gpu)
#ifdef GR_PIPELINE_STATE_CACHE_STATS
    , fTotalRequests(0)
    , fCacheMisses(0)
#endif
{}

GrVkResourceProvider::PipelineStateCache::~PipelineStateCache() {
    SkASSERT(0 == fCount);
    // dump stats
#ifdef GR_PIPELINE_STATE_CACHE_STATS
    if (c_DisplayVkPipelineCache) {
        SkDebugf("--- Pipeline State Cache ---\n");
        SkDebugf("Total requests: %d\n", fTotalRequests);
        SkDebugf("Cache misses: %d\n", fCacheMisses);
        SkDebugf("Cache miss %%: %f\n", (fTotalRequests > 0) ?
                 100.f * fCacheMisses / fTotalRequests :
                 0.f);
        SkDebugf("---------------------\n");
    }
#endif
}

void GrVkResourceProvider::PipelineStateCache::reset() {
    fHashTable.foreach([](Entry** entry) {
        delete *entry;
    });
    fHashTable.reset();
    fCount = 0;
}

void GrVkResourceProvider::PipelineStateCache::abandon() {
    fHashTable.foreach([](Entry** entry) {
        SkASSERT((*entry)->fPipelineState.get());
        (*entry)->fPipelineState->abandonGPUResources();
    });

    this->reset();
}

void GrVkResourceProvider::PipelineStateCache::release() {
    fHashTable.foreach([this](Entry** entry) {
        SkASSERT((*entry)->fPipelineState.get());
        (*entry)->fPipelineState->freeGPUResources(fGpu);
    });

    this->reset();
}

sk_sp<GrVkPipelineState> GrVkResourceProvider::PipelineStateCache::refPipelineState(
                                                               const GrPipeline& pipeline,
                                                               const GrPrimitiveProcessor& primProc,
                                                               GrPrimitiveType primitiveType,
                                                               const GrVkRenderPass& renderPass) {
#ifdef GR_PIPELINE_STATE_CACHE_STATS
    ++fTotalRequests;
#endif
    GrStencilSettings stencil;
    if (pipeline.isStencilEnabled()) {
        GrRenderTarget* rt = pipeline.getRenderTarget();
        // TODO: attach stencil and create settings during render target flush.
        SkASSERT(rt->renderTargetPriv().getStencilAttachment());
        stencil.reset(*pipeline.getUserStencil(), pipeline.hasStencilClip(),
                      rt->renderTargetPriv().numStencilBits());
    }

    // Get GrVkProgramDesc
    GrVkPipelineState::Desc desc;
    if (!GrVkPipelineState::Desc::Build(&desc, primProc, pipeline, stencil,
                                        primitiveType, *fGpu->vkCaps().glslCaps())) {
        GrCapsDebugf(fGpu->caps(), "Failed to build vk program descriptor!\n");
        return nullptr;
    }
    desc.finalize();

    Entry* entry = nullptr;
    if (Entry** entryptr = fHashTable.find(desc)) {
        SkASSERT(*entryptr);
        entry = *entryptr;
    }
    if (!entry) {
#ifdef GR_PIPELINE_STATE_CACHE_STATS
        ++fCacheMisses;
#endif
        sk_sp<GrVkPipelineState> pipelineState(
            GrVkPipelineStateBuilder::CreatePipelineState(fGpu,
                                                          pipeline,
                                                          stencil,
                                                          primProc,
                                                          primitiveType,
                                                          desc,
                                                          renderPass));
        if (nullptr == pipelineState) {
            return nullptr;
        }
        if (fCount < kMaxEntries) {
            entry = new Entry;
            fCount++;
        } else {
            SkASSERT(fCount == kMaxEntries);
            entry = fLRUList.head();
            fLRUList.remove(entry);
            entry->fPipelineState->freeGPUResources(fGpu);
            fHashTable.remove(entry->fPipelineState->getDesc());
        }
        entry->fPipelineState = std::move(pipelineState);
        fHashTable.set(entry);
        fLRUList.addToTail(entry);
        return entry->fPipelineState;
    } else {
        fLRUList.remove(entry);
        fLRUList.addToTail(entry);
    }
    return entry->fPipelineState;
}
