// Copyright 2024 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "dawn/native/vulkan/ResolveTextureLoadingUtilsVk.h"

#include <sstream>
#include <string>
#include <utility>

#include "absl/container/inlined_vector.h"
#include "dawn/common/Assert.h"
#include "dawn/common/Enumerator.h"
#include "dawn/native/BindGroup.h"
#include "dawn/native/Commands.h"
#include "dawn/native/Device.h"
#include "dawn/native/InternalPipelineStore.h"
#include "dawn/native/utils/WGPUHelpers.h"
#include "dawn/native/vulkan/BindGroupLayoutVk.h"
#include "dawn/native/vulkan/BindGroupVk.h"
#include "dawn/native/vulkan/DeviceVk.h"
#include "dawn/native/vulkan/PipelineLayoutVk.h"
#include "dawn/native/vulkan/RenderPipelineVk.h"
#include "dawn/native/vulkan/TextureVk.h"
#include "dawn/native/vulkan/UtilsVulkan.h"
#include "dawn/native/vulkan/VulkanError.h"
#include "dawn/native/webgpu_absl_format.h"

namespace dawn::native::vulkan {

namespace {

constexpr char kBlitToColorVS[] = R"(

@vertex fn vert_fullscreen_quad(
  @builtin(vertex_index) vertex_index : u32,
) -> @builtin(position) vec4f {
  const pos = array(
      vec2f(-1.0, -1.0),
      vec2f( 3.0, -1.0),
      vec2f(-1.0,  3.0));
  return vec4f(pos[vertex_index], 0.0, 1.0);
}
)";

std::string GenerateFS(const BlitColorToColorWithDrawPipelineKey& pipelineKey) {
    std::ostringstream outputStructStream;
    std::ostringstream assignOutputsStream;
    std::ostringstream finalStream;

    finalStream << "enable chromium_internal_input_attachments;";

    for (auto i : IterateBitSet(pipelineKey.attachmentsToExpandResolve)) {
        finalStream << absl::StrFormat(
            "@group(0) @binding(%u) @input_attachment_index(%u) var srcTex%u : "
            "input_attachment<f32>;\n",
            i, i, i);

        outputStructStream << absl::StrFormat("@location(%u) output%u : vec4f,\n", i, i);

        assignOutputsStream << absl::StrFormat(
            "\toutputColor.output%u = inputAttachmentLoad(srcTex%u);\n", i, i);
    }

    finalStream << "struct OutputColor {\n" << outputStructStream.str() << "}\n\n";
    finalStream << R"(
@fragment fn blit_to_color() -> OutputColor {
    var outputColor : OutputColor;
)" << assignOutputsStream.str()
                << R"(
    return outputColor;
})";

    return finalStream.str();
}

ResultOrError<Ref<RenderPipelineBase>> GetOrCreateColorBlitPipeline(
    DeviceBase* device,
    const BlitColorToColorWithDrawPipelineKey& pipelineKey,
    uint8_t colorAttachmentCount) {
    InternalPipelineStore* store = device->GetInternalPipelineStore();
    {
        auto it = store->expandResolveTexturePipelines.find(pipelineKey);
        if (it != store->expandResolveTexturePipelines.end()) {
            return it->second;
        }
    }

    // vertex shader.
    Ref<ShaderModuleBase> vshaderModule;
    DAWN_TRY_ASSIGN(vshaderModule, utils::CreateShaderModule(device, kBlitToColorVS));

    // fragment shader's source will depend on pipeline key.
    std::string fsCode = GenerateFS(pipelineKey);
    Ref<ShaderModuleBase> fshaderModule;
    DAWN_TRY_ASSIGN(fshaderModule, utils::CreateShaderModule(
                                       device, fsCode.c_str(),
                                       {tint::wgsl::Extension::kChromiumInternalInputAttachments}));

    FragmentState fragmentState = {};
    fragmentState.module = fshaderModule.Get();

    // Color target states.
    PerColorAttachment<ColorTargetState> colorTargets = {};
    PerColorAttachment<wgpu::ColorTargetStateExpandResolveTextureDawn> msaaExpandResolveStates{};

    for (auto [i, target] : Enumerate(colorTargets)) {
        target.format = pipelineKey.colorTargetFormats[i];
        // We shouldn't change the color targets that are not involved in.
        if (pipelineKey.resolveTargetsMask[i]) {
            target.nextInChain = &msaaExpandResolveStates[i];
            msaaExpandResolveStates[i].enabled = pipelineKey.attachmentsToExpandResolve[i];
            if (msaaExpandResolveStates[i].enabled) {
                target.writeMask = wgpu::ColorWriteMask::All;
            } else {
                target.writeMask = wgpu::ColorWriteMask::None;
            }
        } else {
            target.writeMask = wgpu::ColorWriteMask::None;
        }
    }

    fragmentState.targetCount = colorAttachmentCount;
    fragmentState.targets = colorTargets.data();

    RenderPipelineDescriptor renderPipelineDesc = {};
    renderPipelineDesc.label = "blit_color_to_color";
    renderPipelineDesc.vertex.module = vshaderModule.Get();
    renderPipelineDesc.fragment = &fragmentState;

    // Depth stencil state.
    DepthStencilState depthStencilState = {};
    if (pipelineKey.depthStencilFormat != wgpu::TextureFormat::Undefined) {
        depthStencilState.format = pipelineKey.depthStencilFormat;

        renderPipelineDesc.depthStencil = &depthStencilState;
    }

    // Multisample state.
    DAWN_ASSERT(pipelineKey.sampleCount > 1);
    renderPipelineDesc.multisample.count = pipelineKey.sampleCount;

    renderPipelineDesc.layout = nullptr;

    Ref<RenderPipelineBase> pipeline;
    DAWN_TRY_ASSIGN(
        pipeline, device->CreateRenderPipeline(&renderPipelineDesc, /*allowInternalBinding=*/true));

    store->expandResolveTexturePipelines.emplace(pipelineKey, pipeline);
    return pipeline;
}

}  // namespace

MaybeError BeginRenderPassAndExpandResolveTextureWithDraw(Device* device,
                                                          CommandRecordingContext* commandContext,
                                                          const BeginRenderPassCmd* renderPass,
                                                          const VkRenderPassBeginInfo& beginInfo) {
    DAWN_ASSERT(device->IsLockedByCurrentThreadIfNeeded());

    // Construct pipeline key
    BlitColorToColorWithDrawPipelineKey pipelineKey;
    ColorAttachmentIndex colorAttachmentCount =
        GetHighestBitIndexPlusOne(renderPass->attachmentState->GetColorAttachmentsMask());
    for (ColorAttachmentIndex colorIdx :
         IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
        const auto& colorAttachment = renderPass->colorAttachments[colorIdx];
        const auto& view = colorAttachment.view;
        DAWN_ASSERT(view != nullptr);
        const Format& format = view->GetFormat();
        TextureComponentType baseType = format.GetAspectInfo(Aspect::Color).baseType;
        // Blitting integer textures are not currently supported.
        DAWN_ASSERT(baseType == TextureComponentType::Float);

        if (colorAttachment.loadOp == wgpu::LoadOp::ExpandResolveTexture) {
            // TODO(42240662): Handle the cases where resolveTarget is altered by workarounds such
            // as ResolveMultipleAttachmentInSeparatePasses/AlwaysResolveIntoZeroLevelAndLayer. We
            // need to careful handle such cases because the render pass' compatibility could be
            // affected as well.
            DAWN_INVALID_IF(colorAttachment.resolveTarget == nullptr,
                            "resolveTarget at %d has been removed by some workarounds. %s doesn't "
                            "support this yet.",
                            colorIdx, colorAttachment.loadOp);
            DAWN_ASSERT(colorAttachment.resolveTarget->GetLayerCount() == 1u);
            DAWN_ASSERT(colorAttachment.resolveTarget->GetDimension() ==
                        wgpu::TextureViewDimension::e2D);
            pipelineKey.attachmentsToExpandResolve.set(colorIdx);
        }
        pipelineKey.resolveTargetsMask.set(colorIdx, colorAttachment.resolveTarget != nullptr);

        pipelineKey.colorTargetFormats[colorIdx] = format.format;
        pipelineKey.sampleCount = view->GetTexture()->GetSampleCount();
    }

    DAWN_ASSERT(pipelineKey.attachmentsToExpandResolve.any());

    pipelineKey.depthStencilFormat = wgpu::TextureFormat::Undefined;
    if (renderPass->depthStencilAttachment.view != nullptr) {
        pipelineKey.depthStencilFormat =
            renderPass->depthStencilAttachment.view->GetFormat().format;
    }

    Ref<RenderPipelineBase> pipeline;
    DAWN_TRY_ASSIGN(pipeline, GetOrCreateColorBlitPipeline(
                                  device, pipelineKey, static_cast<uint8_t>(colorAttachmentCount)));

    RenderPipeline* pipelineVk = ToBackend(pipeline.Get());
    PipelineLayout* layoutVk = ToBackend(pipeline->GetLayout());
    DAWN_ASSERT(layoutVk != nullptr);

    // Construct bind group.
    Ref<BindGroupLayoutBase> bgl;
    DAWN_TRY_ASSIGN(bgl, pipelineVk->GetBindGroupLayout(0));

    Ref<BindGroupBase> bindGroup;
    absl::InlinedVector<BindGroupEntry, kMaxColorAttachments> bgEntries = {};

    for (auto colorIdx : IterateBitSet(pipelineKey.attachmentsToExpandResolve)) {
        const auto& colorAttachment = renderPass->colorAttachments[colorIdx];
        bgEntries.push_back({});
        auto& bgEntry = bgEntries.back();
        bgEntry.binding = static_cast<uint8_t>(colorIdx);
        bgEntry.textureView = colorAttachment.resolveTarget.Get();

        // Transition the resolve texture
        auto* textureVk = static_cast<Texture*>(colorAttachment.resolveTarget->GetTexture());
        textureVk->TransitionUsageNow(commandContext, kResolveAttachmentLoadingUsage,
                                      wgpu::ShaderStage::Fragment,
                                      colorAttachment.resolveTarget->GetSubresourceRange());
    }

    BindGroupDescriptor bgDesc = {};
    bgDesc.layout = bgl.Get();
    bgDesc.entryCount = bgEntries.size();
    bgDesc.entries = bgEntries.data();
    DAWN_TRY_ASSIGN(bindGroup, device->CreateBindGroup(&bgDesc, UsageValidationMode::Internal));
    BindGroup* bindGroupVk = ToBackend(bindGroup.Get());

    // Start the render pass
    VkCommandBuffer commandBuffer = commandContext->commandBuffer;

    device->fn.CmdBeginRenderPass(commandBuffer, &beginInfo, VK_SUBPASS_CONTENTS_INLINE);

    // Draw to perform the blit.
    VkViewport viewport{};
    viewport.x = 0.0f;
    viewport.y = 0.0f;
    viewport.width = static_cast<float>(renderPass->width);
    viewport.height = static_cast<float>(renderPass->height);
    viewport.minDepth = 0.0f;
    viewport.maxDepth = 1.0f;
    device->fn.CmdSetViewport(commandBuffer, 0, 1, &viewport);

    VkRect2D scissor{};
    scissor.offset = {0, 0};
    scissor.extent.width = renderPass->width;
    scissor.extent.height = renderPass->height;
    device->fn.CmdSetScissor(commandBuffer, 0, 1, &scissor);

    device->fn.CmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
                               *pipelineVk->GetHandle());
    device->fn.CmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
                                     *layoutVk->GetHandle(), 0, 1, &*bindGroupVk->GetHandle(), 0,
                                     nullptr);
    device->fn.CmdDraw(commandBuffer, 3, 1, 0, 0);

    device->fn.CmdNextSubpass(commandBuffer, VK_SUBPASS_CONTENTS_INLINE);

    // Subpass dependency automatically transitions the layouts of the resolve textures
    // to RenderAttachment. So we need to notify TextureVk and don't need to use any explicit
    // barriers.
    for (auto colorIdx : IterateBitSet(pipelineKey.attachmentsToExpandResolve)) {
        const auto& colorAttachment = renderPass->colorAttachments[colorIdx];
        auto* textureVk = static_cast<Texture*>(colorAttachment.resolveTarget->GetTexture());
        textureVk->UpdateUsage(wgpu::TextureUsage::RenderAttachment, wgpu::ShaderStage::Fragment,
                               colorAttachment.resolveTarget->GetSubresourceRange());
    }

    return {};
}
}  // namespace dawn::native::vulkan
