// Copyright 2018 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "dawn_native/vulkan/RenderPassCache.h"

#include "common/BitSetIterator.h"
#include "common/HashUtils.h"
#include "dawn_native/vulkan/DeviceVk.h"
#include "dawn_native/vulkan/TextureVk.h"
#include "dawn_native/vulkan/VulkanError.h"

namespace dawn_native { namespace vulkan {

    namespace {
        VkAttachmentLoadOp VulkanAttachmentLoadOp(wgpu::LoadOp op) {
            switch (op) {
                case wgpu::LoadOp::Load:
                    return VK_ATTACHMENT_LOAD_OP_LOAD;
                case wgpu::LoadOp::Clear:
                    return VK_ATTACHMENT_LOAD_OP_CLEAR;
            }
            UNREACHABLE();
        }
    }  // anonymous namespace

    // RenderPassCacheQuery

    void RenderPassCacheQuery::SetColor(ColorAttachmentIndex index,
                                        wgpu::TextureFormat format,
                                        wgpu::LoadOp loadOp,
                                        bool hasResolveTarget) {
        colorMask.set(index);
        colorFormats[index] = format;
        colorLoadOp[index] = loadOp;
        resolveTargetMask[index] = hasResolveTarget;
    }

    void RenderPassCacheQuery::SetDepthStencil(wgpu::TextureFormat format,
                                               wgpu::LoadOp depthLoadOp,
                                               wgpu::LoadOp stencilLoadOp) {
        hasDepthStencil = true;
        depthStencilFormat = format;
        this->depthLoadOp = depthLoadOp;
        this->stencilLoadOp = stencilLoadOp;
    }

    void RenderPassCacheQuery::SetSampleCount(uint32_t sampleCount) {
        this->sampleCount = sampleCount;
    }

    // RenderPassCache

    RenderPassCache::RenderPassCache(Device* device) : mDevice(device) {
    }

    RenderPassCache::~RenderPassCache() {
        std::lock_guard<std::mutex> lock(mMutex);
        for (auto it : mCache) {
            mDevice->fn.DestroyRenderPass(mDevice->GetVkDevice(), it.second, nullptr);
        }

        mCache.clear();
    }

    ResultOrError<VkRenderPass> RenderPassCache::GetRenderPass(const RenderPassCacheQuery& query) {
        std::lock_guard<std::mutex> lock(mMutex);
        auto it = mCache.find(query);
        if (it != mCache.end()) {
            return VkRenderPass(it->second);
        }

        VkRenderPass renderPass;
        DAWN_TRY_ASSIGN(renderPass, CreateRenderPassForQuery(query));
        mCache.emplace(query, renderPass);
        return renderPass;
    }

    ResultOrError<VkRenderPass> RenderPassCache::CreateRenderPassForQuery(
        const RenderPassCacheQuery& query) const {
        // The Vulkan subpasses want to know the layout of the attachments with VkAttachmentRef.
        // Precompute them as they must be pointer-chained in VkSubpassDescription
        std::array<VkAttachmentReference, kMaxColorAttachments> colorAttachmentRefs;
        std::array<VkAttachmentReference, kMaxColorAttachments> resolveAttachmentRefs;
        VkAttachmentReference depthStencilAttachmentRef;

        // Contains the attachment description that will be chained in the create info
        // The order of all attachments in attachmentDescs is "color-depthstencil-resolve".
        constexpr uint8_t kMaxAttachmentCount = kMaxColorAttachments * 2 + 1;
        std::array<VkAttachmentDescription, kMaxAttachmentCount> attachmentDescs = {};

        VkSampleCountFlagBits vkSampleCount = VulkanSampleCount(query.sampleCount);

        uint32_t colorAttachmentIndex = 0;
        for (ColorAttachmentIndex i : IterateBitSet(query.colorMask)) {
            auto& attachmentRef = colorAttachmentRefs[colorAttachmentIndex];
            auto& attachmentDesc = attachmentDescs[colorAttachmentIndex];

            attachmentRef.attachment = colorAttachmentIndex;
            attachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

            attachmentDesc.flags = 0;
            attachmentDesc.format = VulkanImageFormat(mDevice, query.colorFormats[i]);
            attachmentDesc.samples = vkSampleCount;
            attachmentDesc.loadOp = VulkanAttachmentLoadOp(query.colorLoadOp[i]);
            attachmentDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
            attachmentDesc.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
            attachmentDesc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

            ++colorAttachmentIndex;
        }

        uint32_t attachmentCount = colorAttachmentIndex;
        VkAttachmentReference* depthStencilAttachment = nullptr;
        if (query.hasDepthStencil) {
            auto& attachmentDesc = attachmentDescs[attachmentCount];

            depthStencilAttachment = &depthStencilAttachmentRef;

            depthStencilAttachmentRef.attachment = attachmentCount;
            depthStencilAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;

            attachmentDesc.flags = 0;
            attachmentDesc.format = VulkanImageFormat(mDevice, query.depthStencilFormat);
            attachmentDesc.samples = vkSampleCount;
            attachmentDesc.loadOp = VulkanAttachmentLoadOp(query.depthLoadOp);
            attachmentDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
            attachmentDesc.stencilLoadOp = VulkanAttachmentLoadOp(query.stencilLoadOp);
            attachmentDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
            attachmentDesc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
            attachmentDesc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;

            ++attachmentCount;
        }

        uint32_t resolveAttachmentIndex = 0;
        for (ColorAttachmentIndex i : IterateBitSet(query.resolveTargetMask)) {
            auto& attachmentRef = resolveAttachmentRefs[resolveAttachmentIndex];
            auto& attachmentDesc = attachmentDescs[attachmentCount];

            attachmentRef.attachment = attachmentCount;
            attachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

            attachmentDesc.flags = 0;
            attachmentDesc.format = VulkanImageFormat(mDevice, query.colorFormats[i]);
            attachmentDesc.samples = VK_SAMPLE_COUNT_1_BIT;
            attachmentDesc.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
            attachmentDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
            attachmentDesc.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
            attachmentDesc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

            ++attachmentCount;
            ++resolveAttachmentIndex;
        }

        // All color attachments without a corresponding resolve attachment must be set to VK_ATTACHMENT_UNUSED
        for (; resolveAttachmentIndex < colorAttachmentIndex; resolveAttachmentIndex++) {
            auto& attachmentRef = resolveAttachmentRefs[resolveAttachmentIndex];
            attachmentRef.attachment = VK_ATTACHMENT_UNUSED;
            attachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // The Khronos Vulkan validation layer will complain if not set
        }

        VkAttachmentReference* resolveTargetAttachmentRefs =
            query.resolveTargetMask.any() ? resolveAttachmentRefs.data() : nullptr;

        // Create the VkSubpassDescription that will be chained in the VkRenderPassCreateInfo
        VkSubpassDescription subpassDesc;
        subpassDesc.flags = 0;
        subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
        subpassDesc.inputAttachmentCount = 0;
        subpassDesc.pInputAttachments = nullptr;
        subpassDesc.colorAttachmentCount = colorAttachmentIndex;
        subpassDesc.pColorAttachments = colorAttachmentRefs.data();
        subpassDesc.pResolveAttachments = resolveTargetAttachmentRefs;
        subpassDesc.pDepthStencilAttachment = depthStencilAttachment;
        subpassDesc.preserveAttachmentCount = 0;
        subpassDesc.pPreserveAttachments = nullptr;

        // Chain everything in VkRenderPassCreateInfo
        VkRenderPassCreateInfo createInfo;
        createInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
        createInfo.pNext = nullptr;
        createInfo.flags = 0;
        createInfo.attachmentCount = attachmentCount;
        createInfo.pAttachments = attachmentDescs.data();
        createInfo.subpassCount = 1;
        createInfo.pSubpasses = &subpassDesc;
        createInfo.dependencyCount = 0;
        createInfo.pDependencies = nullptr;

        // Create the render pass from the zillion parameters
        VkRenderPass renderPass;
        DAWN_TRY(CheckVkSuccess(mDevice->fn.CreateRenderPass(mDevice->GetVkDevice(), &createInfo,
                                                             nullptr, &*renderPass),
                                "CreateRenderPass"));
        return renderPass;
    }

    // RenderPassCache

    size_t RenderPassCache::CacheFuncs::operator()(const RenderPassCacheQuery& query) const {
        size_t hash = Hash(query.colorMask);

        HashCombine(&hash, Hash(query.resolveTargetMask));

        for (ColorAttachmentIndex i : IterateBitSet(query.colorMask)) {
            HashCombine(&hash, query.colorFormats[i], query.colorLoadOp[i]);
        }

        HashCombine(&hash, query.hasDepthStencil);
        if (query.hasDepthStencil) {
            HashCombine(&hash, query.depthStencilFormat, query.depthLoadOp, query.stencilLoadOp);
        }

        HashCombine(&hash, query.sampleCount);

        return hash;
    }

    bool RenderPassCache::CacheFuncs::operator()(const RenderPassCacheQuery& a,
                                                 const RenderPassCacheQuery& b) const {
        if (a.colorMask != b.colorMask) {
            return false;
        }

        if (a.resolveTargetMask != b.resolveTargetMask) {
            return false;
        }

        if (a.sampleCount != b.sampleCount) {
            return false;
        }

        for (ColorAttachmentIndex i : IterateBitSet(a.colorMask)) {
            if ((a.colorFormats[i] != b.colorFormats[i]) ||
                (a.colorLoadOp[i] != b.colorLoadOp[i])) {
                return false;
            }
        }

        if (a.hasDepthStencil != b.hasDepthStencil) {
            return false;
        }

        if (a.hasDepthStencil) {
            if ((a.depthStencilFormat != b.depthStencilFormat) ||
                (a.depthLoadOp != b.depthLoadOp) || (a.stencilLoadOp != b.stencilLoadOp)) {
                return false;
            }
        }

        return true;
    }
}}  // namespace dawn_native::vulkan
