// 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/tint/lang/hlsl/writer/raise/pixel_local.h"

#include "src/tint/lang/core/ir/block.h"
#include "src/tint/lang/core/ir/builder.h"
#include "src/tint/lang/core/ir/exit.h"
#include "src/tint/lang/core/ir/loop.h"
#include "src/tint/lang/core/ir/switch.h"
#include "src/tint/lang/core/ir/validator.h"
#include "src/tint/lang/core/type/manager.h"
#include "src/tint/lang/hlsl/builtin_fn.h"
#include "src/tint/lang/hlsl/ir/builtin_call.h"
#include "src/tint/lang/hlsl/ir/member_builtin_call.h"
#include "src/tint/lang/hlsl/type/rasterizer_ordered_texture_2d.h"
#include "src/tint/utils/containers/vector.h"
#include "src/tint/utils/ice/ice.h"
#include "src/tint/utils/result/result.h"

namespace tint::hlsl::writer::raise {
namespace {

using namespace tint::core::fluent_types;  // NOLINT

/// PIMPL state for the transform.
struct State {
    // Config options
    const PixelLocalOptions& options;

    /// The IR module.
    core::ir::Module& ir;

    /// The IR builder.
    core::ir::Builder b{ir};

    /// The type manager.
    core::type::Manager& ty{ir.Types()};

    // A Rasterizer Order View (ROV)
    struct ROV {
        core::ir::Var* var;
        core::type::Type* subtype;
    };
    // Create ROV root variables, one per member of `pixel_local_struct`
    Vector<ROV, 4> CreateROVs(const core::type::Struct* pixel_local_struct) {
        Vector<ROV, 4> rovs;
        // Create ROVs for each member of the struct
        for (auto* mem : pixel_local_struct->Members()) {
            auto options_texel_format = options.attachment_formats.find(mem->Index());
            auto options_binding = options.attachments.find(mem->Index());
            if (options_texel_format == options.attachment_formats.end() ||
                options_binding == options.attachments.end()) {
                TINT_ICE() << "missing options for member at index " << mem->Index();
            }
            core::TexelFormat texel_format;
            switch (options_texel_format->second) {
                case PixelLocalOptions::TexelFormat::kR32Sint:
                    texel_format = core::TexelFormat::kR32Sint;
                    break;
                case PixelLocalOptions::TexelFormat::kR32Uint:
                    texel_format = core::TexelFormat::kR32Uint;
                    break;
                case PixelLocalOptions::TexelFormat::kR32Float:
                    texel_format = core::TexelFormat::kR32Float;
                    break;
                default:
                    TINT_ICE() << "missing texel format for pixel local storage attachment";
            }
            auto* subtype = hlsl::type::RasterizerOrderedTexture2D::SubtypeFor(texel_format, ty);

            auto* rov_ty = ty.Get<hlsl::type::RasterizerOrderedTexture2D>(texel_format, subtype);
            auto* rov = b.Var("pixel_local_" + mem->Name().Name(), ty.ptr<handle>(rov_ty));
            rov->SetBindingPoint(options.group_index, options_binding->second);

            ir.root_block->Append(rov);
            rovs.Emplace(rov, subtype);
        }
        return rovs;
    }

    void ProcessFragmentEntryPoint(core::ir::Function* entry_point,
                                   core::ir::Var* pixel_local_var,
                                   const core::type::Struct* pixel_local_struct,
                                   const Vector<ROV, 4>& rovs) {
        TINT_ASSERT(entry_point->Params().Length() == 1);  // Guaranteed by ShaderIO
        core::ir::FunctionParam* entry_point_param = entry_point->Params()[0];

        auto* param_struct = entry_point_param->Type()->As<core::type::Struct>();
        TINT_ASSERT(param_struct);  // Guaranteed by ShaderIO

        // Find the position builtin in the struct
        const core::type::StructMember* position_member = nullptr;
        for (auto* mem : param_struct->Members()) {
            if (mem->Attributes().builtin == core::BuiltinValue::kPosition) {
                position_member = mem;
                break;
            }
        }
        TINT_ASSERT(position_member);

        // Get the entry point's single return instruction. We expect only one as this transform
        // should run after ShaderIO.
        core::ir::Return* entry_point_ret = nullptr;
        if (entry_point->UsagesUnsorted().Count() == 1) {
            entry_point_ret =
                entry_point->UsagesUnsorted().begin()->instruction->As<core::ir::Return>();
        }
        if (!entry_point_ret) {
            TINT_ICE() << "expected entry point with a single return";
        }

        // Change the address space of the var from 'pixel_local' to 'private'
        pixel_local_var->Result(0)->SetType(ty.ptr<private_>(pixel_local_struct));
        // As well as the usages
        for (auto& usage : pixel_local_var->Result(0)->UsagesUnsorted()) {
            if (auto* ptr = usage->instruction->Result(0)->Type()->As<core::type::Pointer>()) {
                usage->instruction->Result(0)->SetType(ty.ptr<private_>(ptr->StoreType()));
            }
        }

        // Insert coord decl used to index ROVs at the entry point start
        core::ir::Instruction* coord = nullptr;
        b.InsertBefore(entry_point->Block()->Front(), [&] {
            coord = b.Access(ty.vec4<f32>(), entry_point_param, u32(position_member->Index()));
            coord = b.Swizzle(ty.vec2<f32>(), coord, {0, 1});
            coord = b.Convert<vec2<u32>>(coord);  // Input type to .Load
        });

        // Insert copy from ROVs to the struct right after the coord decl
        b.InsertAfter(coord, [&] {
            for (auto* mem : pixel_local_struct->Members()) {
                auto& rov = rovs[mem->Index()];
                auto* mem_ty = mem->Type();
                TINT_ASSERT(mem_ty->Is<core::type::Scalar>());
                core::ir::Instruction* from = b.Load(rov.var);
                // Load returns a vec4, so we need to swizzle the first element
                from = b.MemberCall<hlsl::ir::MemberBuiltinCall>(
                    ty.vec4(rov.subtype), tint::hlsl::BuiltinFn::kLoad, from, coord);
                from = b.Swizzle(rov.subtype, from, {0});
                if (mem_ty != rov.subtype) {
                    // ROV and struct member types don't match
                    from = b.Convert(mem_ty, from);
                }
                auto* to = b.Access(ty.ptr<private_>(mem_ty), pixel_local_var, u32(mem->Index()));
                b.Store(to, from);
            }
        });

        // Insert a copy from the struct back to ROVs at the return point
        b.InsertBefore(entry_point_ret, [&] {
            for (auto* mem : pixel_local_struct->Members()) {
                auto& rov = rovs[mem->Index()];
                auto* mem_ty = mem->Type();
                TINT_ASSERT(mem_ty->Is<core::type::Scalar>());
                core::ir::Instruction* from =
                    b.Access(ty.ptr<private_>(mem_ty), pixel_local_var, u32(mem->Index()));
                if (mem_ty != rov.subtype) {
                    // ROV and struct member types don't match
                    from = b.Convert(rov.subtype, from);
                }
                // Store requires a vec4
                from = b.Swizzle(ty.vec4(rov.subtype), from, {0, 0, 0, 0});
                core::ir::Instruction* to = b.Load(rov.var);
                b.Call<hlsl::ir::BuiltinCall>(  //
                    ty.void_(), hlsl::BuiltinFn::kTextureStore, to, coord, from);
            }
        });
    }

    /// Process the module.
    void Process() {
        TINT_ASSERT(options.attachments.size() == options.attachment_formats.size());
        if (options.attachments.size() == 0) {
            return;
        }

        // Inline pointers
        for (auto* inst : ir.Instructions()) {
            if (auto* l = inst->As<core::ir::Let>()) {
                if (l->Result(0)->Type()->Is<core::type::Pointer>()) {
                    l->Result(0)->ReplaceAllUsesWith(l->Value());
                    l->Destroy();
                }
            }
        }

        // Find the pixel_local module var, if any
        core::ir::Var* pixel_local_var = nullptr;
        const core::type::Struct* pixel_local_struct = nullptr;
        for (auto* inst : *ir.root_block) {
            if (auto* var = inst->As<core::ir::Var>()) {
                auto* ptr = var->Result(0)->Type()->As<core::type::Pointer>();
                if (ptr->AddressSpace() == core::AddressSpace::kPixelLocal) {
                    pixel_local_var = var;
                    pixel_local_struct = ptr->StoreType()->As<core::type::Struct>();
                    break;
                }
            }
        }
        if (!pixel_local_var || !pixel_local_var->Result(0)->IsUsed()) {
            return;
        }
        if (!pixel_local_struct) {
            TINT_ICE() << "pixel_local var must be of struct type";
        }
        if (pixel_local_struct->Members().Length() != options.attachments.size()) {
            TINT_ICE() << "missing options for each member of the pixel_local struct";
        }

        auto rovs = CreateROVs(pixel_local_struct);

        for (auto f : ir.functions) {
            if (f->Stage() == core::ir::Function::PipelineStage::kFragment) {
                ProcessFragmentEntryPoint(f, pixel_local_var, pixel_local_struct, rovs);
            }
        }
    }
};

}  // namespace

Result<SuccessType> PixelLocal(core::ir::Module& ir, const PixelLocalConfig& config) {
    auto result = ValidateAndDumpIfNeeded(ir, "PixelLocal transform",
                                          core::ir::Capabilities{
                                              core::ir::Capability::kAllowClipDistancesOnF32,
                                          });
    if (result != Success) {
        return result.Failure();
    }

    State{config.options, ir}.Process();

    return Success;
}

}  // namespace tint::hlsl::writer::raise
