// 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 "src/dawn/native/vulkan/ResolveTextureLoadingUtilsVk.h"

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

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

namespace dawn::native::vulkan {

namespace {

constexpr char kBlitToColorVS[] = DAWN_MULTILINE(
    @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 : pipelineKey.attachmentsToExpandResolve) {
        finalStream << absl::StrFormat(
            "@group(0) @binding(%u) @input_attachment_index(%u) var srcTex%u : "
            "input_attachment<f32>;",
            i, i, i);

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

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

    finalStream << "struct OutputColor {" << outputStructStream.str() << "}";
    finalStream << DAWN_MULTILINE(
        @fragment fn blit_to_color() -> OutputColor {
            var outputColor : OutputColor;
    );
    finalStream << assignOutputsStream.str();
    finalStream << DAWN_MULTILINE(
            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}));

    // 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 fragmentState = {};
    fragmentState.module = fshaderModule.Get();
    fragmentState.targets = colorTargets;

    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;
        depthStencilState.depthWriteEnabled = wgpu::OptionalBool::False;

        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 : 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());

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

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

    for (auto colorIdx : 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.entries = bgEntries;
    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());
    pipelineVk->ApplyDynamicState(commandBuffer, nullptr);
    device->fn.CmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
                                     *pipelineVk->GetVkLayout(), 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 : 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
