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

#include "include/utils/SkBase64.h"
#include "src/core/SkMD5.h"
#include "src/core/SkReadBuffer.h"
#include "src/gpu/ganesh/GrPersistentCacheUtils.h"
#include "tools/gpu/MemoryCache.h"

#if defined(SK_VULKAN)
#include "src/gpu/ganesh/vk/GrVkGpu.h"
#endif

// Change this to 1 to log cache hits/misses/stores using SkDebugf.
#define LOG_MEMORY_CACHE 0

static SkString data_to_str(const SkData& data) {
    size_t encodeLength = SkBase64::Encode(data.data(), data.size(), nullptr);
    SkString str;
    str.resize(encodeLength);
    SkBase64::Encode(data.data(), data.size(), str.writable_str());
    static constexpr size_t kMaxLength = 60;
    static constexpr char kTail[] = "...";
    static const size_t kTailLen = strlen(kTail);
    bool overlength = encodeLength > kMaxLength;
    if (overlength) {
        str = SkString(str.c_str(), kMaxLength - kTailLen);
        str.append(kTail);
    }
    return str;
}

namespace sk_gpu_test {

sk_sp<SkData> MemoryCache::load(const SkData& key) {
    auto result = fMap.find(key);
    if (result == fMap.end()) {
        if (LOG_MEMORY_CACHE) {
            SkDebugf("Load Key: %s\n\tNot Found.\n\n", data_to_str(key).c_str());
        }
        ++fCacheMissCnt;
        return nullptr;
    }
    if (LOG_MEMORY_CACHE) {
        SkDebugf("Load Key: %s\n\tFound Data: %s\n\n", data_to_str(key).c_str(),
                 data_to_str(*result->second.fData).c_str());
    }
    result->second.fHitCount++;
    return result->second.fData;
}

void MemoryCache::store(const SkData& key, const SkData& data, const SkString& description) {
    if (LOG_MEMORY_CACHE) {
        SkDebugf("Store Key: %s\n\tData: %s\n\n", data_to_str(key).c_str(),
                 data_to_str(data).c_str());
    }
    ++fCacheStoreCnt;
    fMap[Key(key)] = Value(data, description);
}

void MemoryCache::writeShadersToDisk(const char* path, GrBackendApi api) {
    if (GrBackendApi::kOpenGL != api && GrBackendApi::kVulkan != api) {
        return;
    }

    for (auto it = fMap.begin(); it != fMap.end(); ++it) {
        SkMD5 hash;
        size_t bytesToHash = it->first.fKey->size();
#if defined(SK_VULKAN)
        if (GrBackendApi::kVulkan == api) {
            // Vulkan stores two kinds of data in the cache (shaders and pipelines). The last four
            // bytes of the key identify which one we have. We only want to extract shaders.
            // Additionally, we don't want to hash the tag bytes, so we get the same keys as GL,
            // which is good for cross-checking code generation and performance.
            GrVkGpu::PersistentCacheKeyType vkKeyType;
            SkASSERT(bytesToHash >= sizeof(vkKeyType));
            bytesToHash -= sizeof(vkKeyType);
            memcpy(&vkKeyType, it->first.fKey->bytes() + bytesToHash, sizeof(vkKeyType));
            if (vkKeyType != GrVkGpu::kShader_PersistentCacheKeyType) {
                continue;
            }
        }
#endif
        hash.write(it->first.fKey->bytes(), bytesToHash);
        SkMD5::Digest digest = hash.finish();
        SkString md5;
        for (int i = 0; i < 16; ++i) {
            md5.appendf("%02x", digest.data[i]);
        }

        SkSL::Program::Inputs inputsIgnored[kGrShaderTypeCount];
        std::string shaders[kGrShaderTypeCount];
        const SkData* data = it->second.fData.get();
        const SkString& description = it->second.fDescription;
        SkReadBuffer reader(data->data(), data->size());
        GrPersistentCacheUtils::GetType(&reader); // Shader type tag
        GrPersistentCacheUtils::UnpackCachedShaders(&reader, shaders,
                                                    inputsIgnored, kGrShaderTypeCount);

        // Even with the SPIR-V switches, it seems like we must use .spv, or malisc tries to
        // run glslang on the input.
        {
            const char* ext = GrBackendApi::kOpenGL == api ? "frag" : "frag.spv";
            SkString filename = SkStringPrintf("%s/%s.%s", path, md5.c_str(), ext);
            SkFILEWStream file(filename.c_str());
            file.write(shaders[kFragment_GrShaderType].c_str(),
                       shaders[kFragment_GrShaderType].size());
        }
        {
            const char* ext = GrBackendApi::kOpenGL == api ? "vert" : "vert.spv";
            SkString filename = SkStringPrintf("%s/%s.%s", path, md5.c_str(), ext);
            SkFILEWStream file(filename.c_str());
            file.write(shaders[kVertex_GrShaderType].c_str(),
                       shaders[kVertex_GrShaderType].size());
        }

        if (!description.isEmpty()) {
            const char* ext = "key";
            SkString filename = SkStringPrintf("%s/%s.%s", path, md5.c_str(), ext);
            SkFILEWStream file(filename.c_str());
            file.write(description.c_str(), description.size());
        }
    }
}

}  // namespace sk_gpu_test
