// Copyright 2025 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/spirv/reader/lower/texture.h"

#include <optional>
#include <tuple>
#include <utility>
#include <vector>

#include "src/tint/lang/core/ir/builder.h"
#include "src/tint/lang/core/ir/clone_context.h"
#include "src/tint/lang/core/ir/module.h"
#include "src/tint/lang/core/ir/validator.h"
#include "src/tint/lang/core/type/sampled_texture.h"
#include "src/tint/lang/core/type/storage_texture.h"
#include "src/tint/lang/spirv/builtin_fn.h"
#include "src/tint/lang/spirv/ir/builtin_call.h"
#include "src/tint/lang/spirv/type/image.h"

namespace tint::spirv::reader::lower {
namespace {

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

enum class ImageOperandsMask : uint32_t {
    kBias = 0x00000001,
    kLod = 0x00000002,
    kGrad = 0x00000004,
    kConstOffset = 0x00000008,
    kSample = 0x00000040,
};

/// PIMPL state for the transform.
struct State {
    /// The IR module.
    core::ir::Module& ir;

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

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

    /// Map of all OpSampledImages seen
    Hashmap<core::ir::Value*, core::ir::Instruction*, 4> sampled_images_{};

    /// Any `ir::UserCall` instructions which have texture params which need to be updated.
    Hashset<core::ir::UserCall*, 2> user_calls_to_convert_{};

    /// The `ir::Values`s which have had their types changed, they then need to have their
    /// usages updated to match. This maps to the root FunctionParam or Var for each texture.
    Vector<core::ir::Value*, 8> values_to_fix_usages_{};

    Vector<core::ir::Let*, 8> lets_to_inline_{};

    /// Function to texture replacements
    Hashmap<core::ir::Function*, core::ir::Function*, 4> func_to_rewritten_{};

    /// Textures used in dref calls which need to be depth textures.
    Vector<core::ir::Value*, 4> textures_to_convert_to_depth_{};
    /// Samplers used in dref calls which need to be comparison samplers
    Vector<core::ir::Value*, 4> samplers_to_convert_to_comparison_{};

    /// Process the module.
    void Process() {
        ReplacePointerToHandle();

        for (auto* inst : *ir.root_block) {
            auto* var = inst->As<core::ir::Var>();
            if (!var) {
                continue;
            }

            auto* ptr = var->Result()->Type()->As<core::type::Pointer>();
            TINT_ASSERT(ptr);

            auto* type = ptr->UnwrapPtr();
            if (!type->IsAnyOf<spirv::type::Image, core::type::Sampler>()) {
                continue;
            }

            auto* new_ty = TypeFor(type);
            if (type->Is<spirv::type::Image>()) {
                var->Result()->SetType(ty.ptr(ptr->AddressSpace(), new_ty, ptr->Access()));
                values_to_fix_usages_.Push(var->Result());
            }

            var->Result()->ForEachUseUnsorted([&](const core::ir::Usage& usage) {
                tint::Switch(
                    usage.instruction,  //
                    [&](core::ir::Load* l) {
                        if (type->Is<spirv::type::Image>()) {
                            l->Result()->SetType(new_ty);
                        }
                    },
                    [&](core::ir::Let* let) {
                        if (type->Is<core::type::Sampler>()) {
                            lets_to_inline_.Push(let);
                        }
                    });
            });
        }

        Vector<spirv::ir::BuiltinCall*, 4> depth_worklist;
        for (auto* inst : ir.Instructions()) {
            if (auto* builtin = inst->As<spirv::ir::BuiltinCall>()) {
                switch (builtin->Func()) {
                    case spirv::BuiltinFn::kOpSampledImage:
                        SampledImage(builtin);
                        break;
                    case spirv::BuiltinFn::kImageDrefGather:
                    case spirv::BuiltinFn::kImageSampleDrefImplicitLod:
                    case spirv::BuiltinFn::kImageSampleDrefExplicitLod:
                    case spirv::BuiltinFn::kImageSampleProjDrefImplicitLod:
                    case spirv::BuiltinFn::kImageSampleProjDrefExplicitLod:
                        depth_worklist.Push(builtin);
                        break;
                    default:
                        break;
                }
            }
        }

        // For each depth function, find the parameters which needed be converted. We don't convert
        // the actual calls yet, as we may need to parameters to have propagated through function
        // parameters.
        for (auto* builtin : depth_worklist) {
            switch (builtin->Func()) {
                case spirv::BuiltinFn::kImageSampleDrefImplicitLod:
                case spirv::BuiltinFn::kImageSampleDrefExplicitLod:
                case spirv::BuiltinFn::kImageSampleProjDrefImplicitLod:
                case spirv::BuiltinFn::kImageSampleProjDrefExplicitLod:
                    FindVarsForImageSampleDref(builtin);
                    break;
                case spirv::BuiltinFn::kImageDrefGather:
                    FindVarsForImageGatherDref(builtin);
                    break;
                default:
                    TINT_UNREACHABLE();
            }
        }

        Hashset<core::ir::Value*, 4> converted{};
        while (!textures_to_convert_to_depth_.IsEmpty()) {
            auto tex = textures_to_convert_to_depth_.Pop();
            if (!converted.Add(tex)) {
                continue;
            }

            tint::Switch(
                FindRootVarFor(tex),  //
                [&](core::ir::InstructionResult* res) {
                    auto* var = res->Instruction()->As<core::ir::Var>();
                    TINT_ASSERT(var);
                    ConvertVarToDepth(var);
                },
                [&](core::ir::FunctionParam* param) { ConvertTextureParam(param); },  //
                TINT_ICE_ON_NO_MATCH);
        }

        while (!samplers_to_convert_to_comparison_.IsEmpty()) {
            auto samp = samplers_to_convert_to_comparison_.Pop();
            if (!converted.Add(samp)) {
                continue;
            }

            tint::Switch(
                FindRootVarFor(samp),  //
                [&](core::ir::InstructionResult* res) {
                    auto* var = res->Instruction()->As<core::ir::Var>();
                    TINT_ASSERT(var);
                    ConvertVarToComparison(var);
                },
                [&](core::ir::FunctionParam* param) { ConvertSamplerParam(param); },  //
                TINT_ICE_ON_NO_MATCH);
        }
        UpdateValues();

        Vector<spirv::ir::BuiltinCall*, 4> builtin_worklist;
        for (auto* inst : ir.Instructions()) {
            if (auto* builtin = inst->As<spirv::ir::BuiltinCall>()) {
                switch (builtin->Func()) {
                    case spirv::BuiltinFn::kOpSampledImage:
                        // Note, we _also_ do this here even though it was done above. The one above
                        // registers for the depth functions, but, we may have forked functions in
                        // the `UpdateValues` when it does the `ConvertUserCall`. This would then
                        // generate new `SampledImage` objects which need to be registered. In the
                        // worse case, we just write the same data twice.
                        SampledImage(builtin);
                        break;
                    case spirv::BuiltinFn::kOpImage:
                    case spirv::BuiltinFn::kImageRead:
                    case spirv::BuiltinFn::kImageFetch:
                    case spirv::BuiltinFn::kImageGather:
                    case spirv::BuiltinFn::kImageQueryLevels:
                    case spirv::BuiltinFn::kImageQuerySamples:
                    case spirv::BuiltinFn::kImageQuerySize:
                    case spirv::BuiltinFn::kImageQuerySizeLod:
                    case spirv::BuiltinFn::kImageSampleExplicitLod:
                    case spirv::BuiltinFn::kImageSampleImplicitLod:
                    case spirv::BuiltinFn::kImageSampleProjImplicitLod:
                    case spirv::BuiltinFn::kImageSampleProjExplicitLod:
                    case spirv::BuiltinFn::kImageWrite:
                    case spirv::BuiltinFn::kImageSampleDrefImplicitLod:
                    case spirv::BuiltinFn::kImageSampleDrefExplicitLod:
                    case spirv::BuiltinFn::kImageSampleProjDrefImplicitLod:
                    case spirv::BuiltinFn::kImageSampleProjDrefExplicitLod:
                    case spirv::BuiltinFn::kImageDrefGather:
                        builtin_worklist.Push(builtin);
                        break;
                    default:
                        TINT_UNREACHABLE() << "unknown spirv builtin: " << builtin->Func();
                }
            }
        }

        for (auto* builtin : builtin_worklist) {
            switch (builtin->Func()) {
                case spirv::BuiltinFn::kOpImage:
                    Image(builtin);
                    break;
                case spirv::BuiltinFn::kImageRead:
                case spirv::BuiltinFn::kImageFetch:
                    ImageFetch(builtin);
                    break;
                case spirv::BuiltinFn::kImageGather:
                    ImageGather(builtin);
                    break;
                case spirv::BuiltinFn::kImageQueryLevels:
                    ImageQuery(builtin, core::BuiltinFn::kTextureNumLevels);
                    break;
                case spirv::BuiltinFn::kImageQuerySamples:
                    ImageQuery(builtin, core::BuiltinFn::kTextureNumSamples);
                    break;
                case spirv::BuiltinFn::kImageQuerySize:
                case spirv::BuiltinFn::kImageQuerySizeLod:
                    ImageQuerySize(builtin);
                    break;
                case spirv::BuiltinFn::kImageSampleExplicitLod:
                case spirv::BuiltinFn::kImageSampleImplicitLod:
                case spirv::BuiltinFn::kImageSampleProjImplicitLod:
                case spirv::BuiltinFn::kImageSampleProjExplicitLod:
                    ImageSample(builtin);
                    break;
                case spirv::BuiltinFn::kImageWrite:
                    ImageWrite(builtin);
                    break;
                case spirv::BuiltinFn::kImageSampleDrefImplicitLod:
                case spirv::BuiltinFn::kImageSampleDrefExplicitLod:
                case spirv::BuiltinFn::kImageSampleProjDrefImplicitLod:
                case spirv::BuiltinFn::kImageSampleProjDrefExplicitLod:
                    ImageSampleDref(builtin);
                    break;
                case spirv::BuiltinFn::kImageDrefGather:
                    ImageGatherDref(builtin);
                    break;
                default:
                    TINT_UNREACHABLE();
            }
        }

        // Destroy all the OpSampledImage instructions.
        for (auto res : sampled_images_) {
            // If the sampled image was in a user function which was forked and the original
            // destroyed then it will no longer be alive.
            if (res.value->Alive()) {
                res.value->Destroy();
            }
        }
    }

    void ReplacePointerToHandle() {
        Vector<core::ir::Value*, 4> usages_to_update;
        Hashset<core::ir::Function*, 4> called_functions_to_fixup;
        for (auto& func : ir.DependencyOrderedFunctions()) {
            for (auto* param : func->Params()) {
                auto* ptr = param->Type()->As<core::type::Pointer>();
                if (!ptr || !ptr->StoreType()->IsHandle()) {
                    continue;
                }

                param->SetType(ptr->StoreType());
                usages_to_update.Push(param);
                called_functions_to_fixup.Add(func);
            }
        }

        Vector<core::ir::Instruction*, 4> inst_to_delete;
        while (!usages_to_update.IsEmpty()) {
            auto* val = usages_to_update.Pop();
            for (auto& usage : val->UsagesSorted()) {
                tint::Switch(
                    usage.instruction,  //
                    [&](core::ir::Load* ld) {
                        ld->Result()->ReplaceAllUsesWith(ld->From());
                        inst_to_delete.Push(ld);
                    },
                    [&](core::ir::Let* l) {
                        for (auto& u : l->Result()->UsagesSorted()) {
                            usages_to_update.Push(u.instruction->Result());
                        }
                        l->Result()->ReplaceAllUsesWith(l->Value());
                        inst_to_delete.Push(l);
                    });
            }
        }

        for (auto& fn : called_functions_to_fixup) {
            for (auto& usage : fn->UsagesUnsorted()) {
                auto* call = usage->instruction->As<core::ir::UserCall>();
                if (!call) {
                    continue;
                }

                auto args = call->Args();
                for (size_t i = 0; i < args.Length(); ++i) {
                    auto& arg = args[i];

                    auto* ptr_ty = arg->Type()->As<core::type::Pointer>();
                    if (!ptr_ty) {
                        continue;
                    }

                    if (!ptr_ty->StoreType()->IsHandle()) {
                        continue;
                    }

                    // We inject the load here but it will get cleaned up when we deal with the
                    // function itself, if required.
                    b.InsertBefore(usage->instruction, [&] {
                        auto* ld = b.Load(arg);
                        call->SetArg(i, ld->Result());
                    });
                }
            }
        }

        while (!inst_to_delete.IsEmpty()) {
            auto* inst = inst_to_delete.Pop();
            inst->Destroy();
        }
    }

    void UpdateValues() {
        // The double loop happens because when we convert user calls, that will
        // add more values to convert, but those values can find user calls to
        // convert, so we have to work until we stabilize
        while (!values_to_fix_usages_.IsEmpty() || !lets_to_inline_.IsEmpty() ||
               !user_calls_to_convert_.IsEmpty()) {
            while (!values_to_fix_usages_.IsEmpty()) {
                auto* val = values_to_fix_usages_.Pop();
                ConvertUsagesToTexture(val);
            }

            while (!lets_to_inline_.IsEmpty()) {
                auto* let = lets_to_inline_.Pop();
                TINT_ASSERT(let->Value());
                let->Result()->ReplaceAllUsesWith(let->Value());
                // We may have done this value already, but push it back on as any of the let usages
                // will now point to it and they need to be updated.
                values_to_fix_usages_.Push(let->Value());
                let->Destroy();
            }

            auto user_calls = user_calls_to_convert_.Vector();
            // Sort for deterministic output
            user_calls.Sort();
            for (auto& call : user_calls) {
                ConvertUserCall(call);
            }
            user_calls_to_convert_.Clear();
        }

        TINT_ASSERT(lets_to_inline_.IsEmpty());
        TINT_ASSERT(values_to_fix_usages_.IsEmpty());
        TINT_ASSERT(user_calls_to_convert_.IsEmpty());
    }

    // Given a value, walk back up and find the root `var`.
    core::ir::Value* FindRootVarFor(core::ir::Value* val) {
        if (val->Is<core::ir::FunctionParam>()) {
            return val;
        }

        auto* inst_res = val->As<core::ir::InstructionResult>();
        TINT_ASSERT(inst_res);
        return tint::Switch(
            inst_res->Instruction(),  //
            [&](core::ir::Let* l) { return FindRootVarFor(l->Value()); },
            [&](core::ir::Load* l) { return FindRootVarFor(l->From()); },
            [&](core::ir::Var* v) { return v->Result(); },  //
            TINT_ICE_ON_NO_MATCH);
    }

    // Given a function parameter to convert to either a depth texture or comparison sampler we get
    // all the call sites for the function. We then mark the argument value for the given parameter
    // for conversion. This will then trigger that variable to convert up the call stack. Eventually
    // we'll stop and convert the root variable. Then, that conversion will trigger a walk back down
    // which will convert the call argument types and do any forking of functions to handle the new
    // parameter types.
    void ConvertTextureParam(core::ir::FunctionParam* param) {
        for (auto& usage : param->Function()->UsagesUnsorted()) {
            auto* caller = usage->instruction->As<core::ir::UserCall>();
            if (!caller) {
                continue;
            }
            textures_to_convert_to_depth_.Push(caller->Args()[param->Index()]);
        }
    }
    void ConvertSamplerParam(core::ir::FunctionParam* param) {
        for (auto& usage : param->Function()->UsagesUnsorted()) {
            auto* caller = usage->instruction->As<core::ir::UserCall>();
            if (!caller) {
                continue;
            }
            samplers_to_convert_to_comparison_.Push(caller->Args()[param->Index()]);
        }
    }

    void ConvertVarToDepth(core::ir::Var* var) {
        auto* orig_ptr_ty = var->Result()->Type()->As<core::type::Pointer>();
        TINT_ASSERT(orig_ptr_ty);

        auto* orig_tex_ty = orig_ptr_ty->UnwrapPtr()->As<core::type::Texture>();
        TINT_ASSERT(orig_tex_ty);

        const core::type::Type* depth_ty = nullptr;
        if (orig_tex_ty->Is<core::type::MultisampledTexture>()) {
            depth_ty = ty.depth_multisampled_texture(orig_tex_ty->Dim());
        } else {
            depth_ty = ty.depth_texture(orig_tex_ty->Dim());
        }

        auto* depth_ptr = ty.ptr(orig_ptr_ty->AddressSpace(), depth_ty, orig_ptr_ty->Access());
        var->Result()->SetType(depth_ptr);

        values_to_fix_usages_.Push(var->Result());
    }

    void ConvertVarToComparison(core::ir::Var* var) {
        auto* orig_ptr_ty = var->Result()->Type()->As<core::type::Pointer>();
        TINT_ASSERT(orig_ptr_ty);

        auto* sampler = ty.comparison_sampler();
        auto* sampler_ptr = ty.ptr(orig_ptr_ty->AddressSpace(), sampler, orig_ptr_ty->Access());
        var->Result()->SetType(sampler_ptr);

        values_to_fix_usages_.Push(var->Result());
    }

    // Stores information for operands which need to be updated with the new load result.
    struct ReplacementValue {
        // The instruction to update
        core::ir::Instruction* instruction;
        // The operand index to insert into
        size_t idx;
        // The new value to insert into the instruction operands at `idx`
        core::ir::Value* value;
    };

    void ConvertUsagesToTexture(core::ir::Value* val) {
        val->ForEachUseUnsorted([&](const core::ir::Usage& usage) {
            auto* inst = usage.instruction;

            tint::Switch(  //
                inst,      //
                [&](core::ir::Let* l) { lets_to_inline_.Push(l); },
                [&](core::ir::Load* l) {
                    auto* res = l->Result();
                    res->SetType(val->Type()->UnwrapPtr());
                    values_to_fix_usages_.Push(res);
                },  //
                [&](core::ir::UserCall* uc) { user_calls_to_convert_.Add(uc); },
                [&](core::ir::BuiltinCall*) {},  //
                TINT_ICE_ON_NO_MATCH);
        });
    }

    // The user calls need to check all of the parameters which were converted
    // to textures and create a forked function call for that combination of
    // parameters.
    void ConvertUserCall(core::ir::UserCall* uc) {
        auto* target = uc->Target();
        auto& params = target->Params();
        const auto& args = uc->Args();

        Vector<size_t, 2> to_convert;
        for (size_t i = 0; i < args.Length(); ++i) {
            if (params[i]->Type() != args[i]->Type()) {
                to_convert.Push(i);
            }
        }
        // Everything is already converted we're done.
        if (to_convert.IsEmpty()) {
            return;
        }

        auto* new_fn = func_to_rewritten_.GetOrAdd(target, [&] {
            core::ir::CloneContext ctx{ir};
            auto* fn = uc->Target()->Clone(ctx);
            ir.functions.Push(fn);

            for (auto idx : to_convert) {
                auto* p = fn->Params()[idx];
                p->SetType(args[idx]->Type());
                values_to_fix_usages_.Push(p);
            }
            return fn;
        });
        uc->SetTarget(new_fn);

        if (target->IsEntryPoint()) {
            return;
        }

        // Check if any of the usages are calls, if they aren't we can destroy the function.
        for (auto& usage : target->UsagesUnsorted()) {
            if (usage->instruction->Is<core::ir::Call>()) {
                return;
            }
        }
        ir.Destroy(target);
    }

    // Record the sampled image so we can extract the texture/sampler information as we process the
    // builtins. It will be destroyed after all builtins are done.
    void SampledImage(spirv::ir::BuiltinCall* call) { sampled_images_.Add(call->Result(), call); }

    std::pair<core::ir::Value*, core::ir::Value*> GetTextureSampler(core::ir::Value* sampled) {
        auto res = sampled_images_.Get(sampled);
        TINT_ASSERT(res);

        core::ir::Instruction* inst = *res;
        TINT_ASSERT(inst->Operands().Length() == 2);

        return {inst->Operands()[0], inst->Operands()[1]};
    }

    uint32_t CoordsRequiredForDim(core::type::TextureDimension dim, bool is_proj) {
        uint32_t ret = 0;
        if (is_proj) {
            ++ret;
        }

        switch (dim) {
            case core::type::TextureDimension::k1d:
                ret += 1;
                break;
            case core::type::TextureDimension::k2d:
                ret += 2;
                break;
            case core::type::TextureDimension::k2dArray:
            case core::type::TextureDimension::k3d:
            case core::type::TextureDimension::kCube:
                ret += 3;
                break;
            case core::type::TextureDimension::kCubeArray:
                ret += 4;
                break;
            default:
                TINT_UNREACHABLE();
        }

        return ret;
    }

    uint32_t Length(const core::type::Type* type) {
        if (type->IsScalar()) {
            return 1;
        }
        if (auto* vec = type->As<core::type::Vector>()) {
            return vec->Width();
        }
        TINT_UNREACHABLE();
    }

    void ProcessCoords(const core::type::Type* type,
                       bool is_proj,
                       core::ir::Value* coords,
                       Vector<core::ir::Value*, 5>& new_args) {
        auto* tex_ty = type->As<core::type::Texture>();
        TINT_ASSERT(tex_ty);

        auto coords_received = Length(coords->Type());

        auto mk_coords = [&](uint32_t count) -> core::ir::Value* {
            if (count == coords_received) {
                return coords;
            }

            Vector<uint32_t, 3> swizzle_idx = {0};
            for (uint32_t i = 1; i < count; ++i) {
                swizzle_idx.Push(i);
            }

            auto* new_ty = ty.MatchWidth(coords->Type()->DeepestElement(), count);
            return b.Swizzle(new_ty, coords, swizzle_idx)->Result();
        };

        auto coords_needed = CoordsRequiredForDim(tex_ty->Dim(), is_proj);
        TINT_ASSERT(coords_needed <= coords_received);

        if (!is_proj && !IsTextureArray(tex_ty->Dim())) {
            new_args.Push(mk_coords(coords_needed));
            return;
        }

        auto* coords_ty = coords->Type()->As<core::type::Vector>();
        TINT_ASSERT(coords_ty);

        // The array / projection index, is on the end
        uint32_t new_coords_width = coords_needed - 1;
        auto* new_coords_ty = ty.MatchWidth(coords_ty->Type(), new_coords_width);

        auto* swizzle = mk_coords(new_coords_width);
        core::ir::Value* last =
            b.Swizzle(coords_ty->Type(), coords, Vector{new_coords_width})->Result();

        if (is_proj) {
            // New coords
            // Divide the coordinates by the last value to simulate the
            // projection behaviour.
            new_args.Push(b.Divide(swizzle, last)->Result());
        } else {
            TINT_ASSERT(new_coords_ty->Is<core::type::Vector>());

            // New coords
            new_args.Push(swizzle);
            // Array index
            if (!last->Type()->Is<core::type::I32>()) {
                last = b.Convert(ty.i32(), last)->Result();
            }
            new_args.Push(last);
        }
    }

    void ProcessOffset(core::ir::Value* offset, Vector<core::ir::Value*, 5>& new_args) {
        if (offset->Type()->IsSignedIntegerVector()) {
            new_args.Push(offset);
            return;
        }

        auto* vec_ty = offset->Type()->As<core::type::Vector>();
        TINT_ASSERT(vec_ty);

        auto* ir_constant = offset->As<core::ir::Constant>();
        TINT_ASSERT(ir_constant);

        auto* constant_value = ir_constant->Value();

        Vector<const core::constant::Value*, 4> new_values;
        for (size_t i = 0; i < vec_ty->Width(); ++i) {
            uint32_t v = constant_value->Index(i)->ValueAs<uint32_t>();
            new_values.Push(b.ConstantValue(i32(v)));
        }

        auto* new_offset = b.Composite(ty.vec(ty.i32(), vec_ty->Width()), new_values);
        new_args.Push(new_offset);
    }

    uint32_t GetOperandMask(core::ir::Value* val) {
        auto* op = val->As<core::ir::Constant>();
        TINT_ASSERT(op);
        return op->Value()->ValueAs<uint32_t>();
    }

    bool HasBias(uint32_t mask) {
        return (mask & static_cast<uint32_t>(ImageOperandsMask::kBias)) != 0;
    }
    bool HasGrad(uint32_t mask) {
        return (mask & static_cast<uint32_t>(ImageOperandsMask::kGrad)) != 0;
    }
    bool HasLod(uint32_t mask) {
        return (mask & static_cast<uint32_t>(ImageOperandsMask::kLod)) != 0;
    }
    bool HasConstOffset(uint32_t mask) {
        return (mask & static_cast<uint32_t>(ImageOperandsMask::kConstOffset)) != 0;
    }
    bool HasSample(uint32_t mask) {
        return (mask & static_cast<uint32_t>(ImageOperandsMask::kSample)) != 0;
    }

    void Image(spirv::ir::BuiltinCall* call) {
        const auto& args = call->Args();
        core::ir::Value* tex = nullptr;
        [[maybe_unused]] core::ir::Value* sampler = nullptr;
        std::tie(tex, sampler) = GetTextureSampler(args[0]);

        call->Result()->ReplaceAllUsesWith(tex);
        call->Destroy();
    }

    void ImageFetch(spirv::ir::BuiltinCall* call) {
        const auto& args = call->Args();

        b.InsertBefore(call, [&] {
            core::ir::Value* tex = args[0];
            auto* coords = args[1];

            auto* tex_ty = tex->Type();
            uint32_t operand_mask = GetOperandMask(args[2]);

            Vector<core::ir::Value*, 5> new_args = {tex};
            ProcessCoords(tex->Type(), false, coords, new_args);

            uint32_t idx = 3;
            if (HasLod(operand_mask)) {
                core::ir::Value* lod = args[idx++];

                if (!lod->Type()->Is<core::type::I32>()) {
                    lod = b.Convert(ty.i32(), lod)->Result();
                }
                new_args.Push(lod);
            } else if (!tex_ty->IsAnyOf<core::type::DepthMultisampledTexture,
                                        core::type::MultisampledTexture,
                                        core::type::StorageTexture>()) {
                // textureLoad requires an explicit level-of-detail parameter for non-multisampled
                // and non-storage texture types.
                new_args.Push(b.Zero(ty.i32()));
            }
            if (HasSample(operand_mask)) {
                core::ir::Value* sample = args[idx++];

                if (!sample->Type()->Is<core::type::I32>()) {
                    sample = b.Convert(ty.i32(), sample)->Result();
                }
                new_args.Push(sample);
            }

            // Depth textures have a single value return in WGSL, but a vec4 in SPIR-V.
            auto* call_ty = call->Result()->Type();
            if (tex_ty->IsAnyOf<core::type::DepthTexture, core::type::DepthMultisampledTexture>()) {
                call_ty = call_ty->DeepestElement();
            }
            auto* res = b.Call(call_ty, core::BuiltinFn::kTextureLoad, new_args)->Result();

            // Restore the vec4 result by padding with 0's.
            if (call_ty != call->Result()->Type()) {
                auto* vec = call->Result()->Type()->As<core::type::Vector>();
                TINT_ASSERT(vec && vec->Width() == 4);

                auto* z = b.Zero(call_ty);
                res = b.Construct(call->Result()->Type(), res, z, z, z)->Result();
            }
            call->Result()->ReplaceAllUsesWith(res);
        });
        call->Destroy();
    }

    void FindVarsForImageGatherDref(spirv::ir::BuiltinCall* call) {
        const auto& args = call->Args();

        core::ir::Value* tex = nullptr;
        core::ir::Value* sampler = nullptr;
        std::tie(tex, sampler) = GetTextureSampler(args[0]);

        textures_to_convert_to_depth_.Push(tex);
        samplers_to_convert_to_comparison_.Push(sampler);
    }

    void ImageGatherDref(spirv::ir::BuiltinCall* call) {
        const auto& args = call->Args();

        b.InsertBefore(call, [&] {
            core::ir::Value* tex = nullptr;
            core::ir::Value* sampler = nullptr;
            std::tie(tex, sampler) = GetTextureSampler(args[0]);

            auto* coords = args[1];
            auto* dref = args[2];

            uint32_t operand_mask = GetOperandMask(args[3]);

            Vector<core::ir::Value*, 5> new_args;

            new_args.Push(tex);
            new_args.Push(sampler);

            ProcessCoords(tex->Type(), false, coords, new_args);
            new_args.Push(dref);

            if (HasConstOffset(operand_mask)) {
                ProcessOffset(args[4], new_args);
            }

            b.CallWithResult(call->DetachResult(), core::BuiltinFn::kTextureGatherCompare,
                             new_args);
        });
        call->Destroy();
    }

    void ImageGather(spirv::ir::BuiltinCall* call) {
        const auto& args = call->Args();

        b.InsertBefore(call, [&] {
            core::ir::Value* tex = nullptr;
            core::ir::Value* sampler = nullptr;
            std::tie(tex, sampler) = GetTextureSampler(args[0]);

            auto* coords = args[1];
            auto* component = args[2];

            uint32_t operand_mask = GetOperandMask(args[3]);

            Vector<core::ir::Value*, 5> new_args;
            if (!tex->Type()->Is<core::type::DepthTexture>()) {
                new_args.Push(component);
            }
            new_args.Push(tex);
            new_args.Push(sampler);

            ProcessCoords(tex->Type(), false, coords, new_args);

            if (HasConstOffset(operand_mask)) {
                ProcessOffset(args[4], new_args);
            }

            b.CallWithResult(call->DetachResult(), core::BuiltinFn::kTextureGather, new_args);
        });
        call->Destroy();
    }

    void FindVarsForImageSampleDref(spirv::ir::BuiltinCall* call) {
        const auto& args = call->Args();

        auto* sampled_image = args[0];

        core::ir::Value* tex = nullptr;
        core::ir::Value* sampler = nullptr;
        std::tie(tex, sampler) = GetTextureSampler(sampled_image);

        textures_to_convert_to_depth_.Push(tex);
        samplers_to_convert_to_comparison_.Push(sampler);
    }

    void ImageSampleDref(spirv::ir::BuiltinCall* call) {
        const auto& args = call->Args();

        auto* sampled_image = args[0];

        core::ir::Value* tex = nullptr;
        core::ir::Value* sampler = nullptr;
        std::tie(tex, sampler) = GetTextureSampler(sampled_image);

        auto* tex_ty = tex->Type();

        auto* coords = args[1];
        auto* depth = args[2];
        uint32_t operand_mask = GetOperandMask(args[3]);

        bool is_proj = call->Func() == spirv::BuiltinFn::kImageSampleProjDrefImplicitLod ||
                       call->Func() == spirv::BuiltinFn::kImageSampleProjDrefExplicitLod;

        uint32_t idx = 4;
        b.InsertBefore(call, [&] {
            Vector<core::ir::Value*, 5> new_args;
            new_args.Push(tex);
            new_args.Push(sampler);

            ProcessCoords(tex_ty, is_proj, coords, new_args);
            new_args.Push(depth);

            auto fn = core::BuiltinFn::kTextureSampleCompare;
            if (HasLod(operand_mask)) {
                fn = core::BuiltinFn::kTextureSampleCompareLevel;
                idx++;  // Skip over the index

                // Metal only supports Lod = 0 for comparison sampling without derivatives. So, WGSL
                // doesn't take a level value, drop the LOD param.
            }
            if (HasConstOffset(operand_mask)) {
                ProcessOffset(args[idx++], new_args);
            }

            b.CallWithResult(call->DetachResult(), fn, new_args);
        });

        call->Destroy();
    }

    void ImageSample(spirv::ir::BuiltinCall* call) {
        const auto& args = call->Args();

        auto* sampled_image = args[0];

        core::ir::Value* tex = nullptr;
        core::ir::Value* sampler = nullptr;
        std::tie(tex, sampler) = GetTextureSampler(sampled_image);

        auto* tex_ty = tex->Type();

        auto* coords = args[1];
        uint32_t operand_mask = GetOperandMask(args[2]);

        bool is_proj = call->Func() == spirv::BuiltinFn::kImageSampleProjImplicitLod ||
                       call->Func() == spirv::BuiltinFn::kImageSampleProjExplicitLod;

        uint32_t idx = 3;
        b.InsertBefore(call, [&] {
            Vector<core::ir::Value*, 5> new_args;
            new_args.Push(tex);
            new_args.Push(sampler);

            ProcessCoords(tex_ty, is_proj, coords, new_args);

            core::BuiltinFn fn = core::BuiltinFn::kTextureSample;
            if (HasBias(operand_mask)) {
                fn = core::BuiltinFn::kTextureSampleBias;
                new_args.Push(args[idx++]);
            }
            if (HasLod(operand_mask)) {
                fn = core::BuiltinFn::kTextureSampleLevel;

                core::ir::Value* lod = args[idx++];

                // Depth texture LOD in WGSL is i32/u32 but f32 in SPIR-V.
                // Convert to i32
                if (tex_ty->Is<core::type::DepthTexture>()) {
                    lod = b.Convert(ty.i32(), lod)->Result();
                }
                new_args.Push(lod);
            }
            if (HasGrad(operand_mask)) {
                fn = core::BuiltinFn::kTextureSampleGrad;
                new_args.Push(args[idx++]);  // ddx
                new_args.Push(args[idx++]);  // ddy
            }
            if (HasConstOffset(operand_mask)) {
                ProcessOffset(args[idx++], new_args);
            }

            // Depth textures have a single value return in WGSL, but a vec4 in SPIR-V.
            auto* call_ty = call->Result()->Type();
            if (tex_ty->IsAnyOf<core::type::DepthTexture, core::type::DepthMultisampledTexture>()) {
                call_ty = call_ty->DeepestElement();
            }
            auto* res = b.Call(call_ty, fn, new_args)->Result();

            // Restore the vec4 result by padding with 0's.
            if (call_ty != call->Result()->Type()) {
                auto* vec = call->Result()->Type()->As<core::type::Vector>();
                TINT_ASSERT(vec && vec->Width() == 4);

                auto* z = b.Zero(call_ty);
                res = b.Construct(call->Result()->Type(), res, z, z, z)->Result();
            }

            call->Result()->ReplaceAllUsesWith(res);
        });
        call->Destroy();
    }

    void ImageWrite(spirv::ir::BuiltinCall* call) {
        const auto& args = call->Args();

        b.InsertBefore(call, [&] {
            core::ir::Value* tex = args[0];
            auto* coords = args[1];
            auto* texel = args[2];

            Vector<core::ir::Value*, 5> new_args;
            new_args.Push(tex);

            ProcessCoords(tex->Type(), false, coords, new_args);

            new_args.Push(texel);

            b.Call(call->Result()->Type(), core::BuiltinFn::kTextureStore, new_args);
        });
        call->Destroy();
    }

    void ImageQuery(spirv::ir::BuiltinCall* call, core::BuiltinFn fn) {
        auto* image = call->Args()[0];

        b.InsertBefore(call, [&] {
            auto* type = call->Result()->Type();

            // WGSL requires a `u32` result component where SPIR-V allows `i32` or `u32`
            core::ir::Value* res =
                b.Call(ty.MatchWidth(ty.u32(), type), fn, Vector{image})->Result();
            if (type->IsSignedIntegerScalarOrVector()) {
                res = b.Convert(type, res)->Result();
            }

            call->Result()->ReplaceAllUsesWith(res);
        });
        call->Destroy();
    }

    void ImageQuerySize(spirv::ir::BuiltinCall* call) {
        auto* image = call->Args()[0];

        auto* tex_ty = image->Type()->As<core::type::Texture>();
        TINT_ASSERT(tex_ty);

        b.InsertBefore(call, [&] {
            auto* type = call->Result()->Type();

            // WGSL requires a `u32` result component where SPIR-V allows `i32` or `u32`
            auto* wgsl_type = ty.MatchWidth(ty.u32(), type);

            // A SPIR-V OpImageQuery will return the array `element` entry with
            // the image query. In WGSL, these are two calls, the
            // `textureDimensions` will get the width,height,depth but we also
            // have to call `textureNumLayers` to get the elements and then
            // re-inject that back into the result.
            if (core::type::IsTextureArray(tex_ty->Dim())) {
                wgsl_type = ty.vec(ty.u32(), wgsl_type->As<core::type::Vector>()->Width() - 1);
            }

            Vector<core::ir::Value*, 2> args = {image};
            if (call->Func() == spirv::BuiltinFn::kImageQuerySizeLod) {
                args.Push(call->Args()[1]);
            }

            core::ir::Value* res =
                b.Call(wgsl_type, core::BuiltinFn::kTextureDimensions, args)->Result();

            if (core::type::IsTextureArray(tex_ty->Dim())) {
                core::ir::Value* layers =
                    b.Call(ty.u32(), core::BuiltinFn::kTextureNumLayers, image)->Result();
                res = b.Construct(ty.MatchWidth(ty.u32(), type), res, layers)->Result();
            }

            if (type->IsSignedIntegerScalarOrVector()) {
                res = b.Convert(type, res)->Result();
            }

            call->Result()->ReplaceAllUsesWith(res);
        });
        call->Destroy();
    }

    const core::type::Type* TypeFor(const core::type::Type* src_ty) {
        if (auto* img = src_ty->As<spirv::type::Image>()) {
            return TypeForImage(img);
        }
        return src_ty;
    }

    core::type::TextureDimension ConvertDim(spirv::type::Dim dim, spirv::type::Arrayed arrayed) {
        switch (dim) {
            case spirv::type::Dim::kD1:
                return core::type::TextureDimension::k1d;
            case spirv::type::Dim::kD2:
                return arrayed == spirv::type::Arrayed::kArrayed
                           ? core::type::TextureDimension::k2dArray
                           : core::type::TextureDimension::k2d;
            case spirv::type::Dim::kD3:
                return core::type::TextureDimension::k3d;
            case spirv::type::Dim::kCube:
                return arrayed == spirv::type::Arrayed::kArrayed
                           ? core::type::TextureDimension::kCubeArray
                           : core::type::TextureDimension::kCube;
            default:
                TINT_UNREACHABLE();
        }
    }

    const core::type::Type* TypeForImage(const spirv::type::Image* img) {
        if (img->GetDim() == spirv::type::Dim::kSubpassData) {
            return ty.input_attachment(img->GetSampledType());
        }

        if (img->GetSampled() == spirv::type::Sampled::kReadWriteOpCompatible) {
            return ty.storage_texture(ConvertDim(img->GetDim(), img->GetArrayed()),
                                      img->GetTexelFormat(), img->GetAccess());
        }

        if (img->GetDepth() == spirv::type::Depth::kDepth) {
            if (img->GetMultisampled() == spirv::type::Multisampled::kMultisampled) {
                return ty.depth_multisampled_texture(ConvertDim(img->GetDim(), img->GetArrayed()));
            }
            return ty.depth_texture(ConvertDim(img->GetDim(), img->GetArrayed()));
        }

        if (img->GetMultisampled() == spirv::type::Multisampled::kMultisampled) {
            return ty.multisampled_texture(ConvertDim(img->GetDim(), img->GetArrayed()),
                                           img->GetSampledType());
        }

        return ty.sampled_texture(ConvertDim(img->GetDim(), img->GetArrayed()),
                                  img->GetSampledType());
    }
};

}  // namespace

Result<SuccessType> Texture(core::ir::Module& ir) {
    TINT_CHECK_RESULT(ValidateBeforeIfNeeded(ir,
                                             core::ir::Capabilities{
                                                 core::ir::Capability::kAllowMultipleEntryPoints,
                                                 core::ir::Capability::kAllowOverrides,
                                                 core::ir::Capability::kAllowNonCoreTypes,
                                                 core::ir::Capability::kAllowPointerToHandle,
                                             },
                                             "spirv.Texture"));

    State{ir}.Process();

    return Success;
}

}  // namespace tint::spirv::reader::lower
