// Copyright 2020 The Tint 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 "src/transform/vertex_pulling.h"

#include <algorithm>
#include <utility>

#include "src/ast/assignment_statement.h"
#include "src/ast/bitcast_expression.h"
#include "src/ast/struct_block_decoration.h"
#include "src/ast/variable_decl_statement.h"
#include "src/program_builder.h"
#include "src/sem/variable.h"
#include "src/utils/get_or_create.h"
#include "src/utils/math.h"

TINT_INSTANTIATE_TYPEINFO(tint::transform::VertexPulling);
TINT_INSTANTIATE_TYPEINFO(tint::transform::VertexPulling::Config);

namespace tint {
namespace transform {

namespace {

/// The base type of a component.
/// The format type is either this type or a vector of this type.
enum class BaseType {
  kInvalid,
  kU32,
  kI32,
  kF32,
};

/// Writes the BaseType to the std::ostream.
/// @param out the std::ostream to write to
/// @param format the BaseType to write
/// @returns out so calls can be chained
std::ostream& operator<<(std::ostream& out, BaseType format) {
  switch (format) {
    case BaseType::kInvalid:
      return out << "invalid";
    case BaseType::kU32:
      return out << "u32";
    case BaseType::kI32:
      return out << "i32";
    case BaseType::kF32:
      return out << "f32";
  }
  return out << "<unknown>";
}

/// Writes the VertexFormat to the std::ostream.
/// @param out the std::ostream to write to
/// @param format the VertexFormat to write
/// @returns out so calls can be chained
std::ostream& operator<<(std::ostream& out, VertexFormat format) {
  switch (format) {
    case VertexFormat::kUint8x2:
      return out << "uint8x2";
    case VertexFormat::kUint8x4:
      return out << "uint8x4";
    case VertexFormat::kSint8x2:
      return out << "sint8x2";
    case VertexFormat::kSint8x4:
      return out << "sint8x4";
    case VertexFormat::kUnorm8x2:
      return out << "unorm8x2";
    case VertexFormat::kUnorm8x4:
      return out << "unorm8x4";
    case VertexFormat::kSnorm8x2:
      return out << "snorm8x2";
    case VertexFormat::kSnorm8x4:
      return out << "snorm8x4";
    case VertexFormat::kUint16x2:
      return out << "uint16x2";
    case VertexFormat::kUint16x4:
      return out << "uint16x4";
    case VertexFormat::kSint16x2:
      return out << "sint16x2";
    case VertexFormat::kSint16x4:
      return out << "sint16x4";
    case VertexFormat::kUnorm16x2:
      return out << "unorm16x2";
    case VertexFormat::kUnorm16x4:
      return out << "unorm16x4";
    case VertexFormat::kSnorm16x2:
      return out << "snorm16x2";
    case VertexFormat::kSnorm16x4:
      return out << "snorm16x4";
    case VertexFormat::kFloat16x2:
      return out << "float16x2";
    case VertexFormat::kFloat16x4:
      return out << "float16x4";
    case VertexFormat::kFloat32:
      return out << "float32";
    case VertexFormat::kFloat32x2:
      return out << "float32x2";
    case VertexFormat::kFloat32x3:
      return out << "float32x3";
    case VertexFormat::kFloat32x4:
      return out << "float32x4";
    case VertexFormat::kUint32:
      return out << "uint32";
    case VertexFormat::kUint32x2:
      return out << "uint32x2";
    case VertexFormat::kUint32x3:
      return out << "uint32x3";
    case VertexFormat::kUint32x4:
      return out << "uint32x4";
    case VertexFormat::kSint32:
      return out << "sint32";
    case VertexFormat::kSint32x2:
      return out << "sint32x2";
    case VertexFormat::kSint32x3:
      return out << "sint32x3";
    case VertexFormat::kSint32x4:
      return out << "sint32x4";
  }
  return out << "<unknown>";
}

/// A vertex attribute data format.
struct DataType {
  BaseType base_type;
  uint32_t width;  // 1 for scalar, 2+ for a vector
};

DataType DataTypeOf(sem::Type* ty) {
  if (ty->Is<sem::I32>()) {
    return {BaseType::kI32, 1};
  }
  if (ty->Is<sem::U32>()) {
    return {BaseType::kU32, 1};
  }
  if (ty->Is<sem::F32>()) {
    return {BaseType::kF32, 1};
  }
  if (auto* vec = ty->As<sem::Vector>()) {
    return {DataTypeOf(vec->type()).base_type, vec->Width()};
  }
  return {BaseType::kInvalid, 0};
}

DataType DataTypeOf(VertexFormat format) {
  switch (format) {
    case VertexFormat::kUint32:
      return {BaseType::kU32, 1};
    case VertexFormat::kUint8x2:
    case VertexFormat::kUint16x2:
    case VertexFormat::kUint32x2:
      return {BaseType::kU32, 2};
    case VertexFormat::kUint32x3:
      return {BaseType::kU32, 3};
    case VertexFormat::kUint8x4:
    case VertexFormat::kUint16x4:
    case VertexFormat::kUint32x4:
      return {BaseType::kU32, 4};
    case VertexFormat::kSint32:
      return {BaseType::kI32, 1};
    case VertexFormat::kSint8x2:
    case VertexFormat::kSint16x2:
    case VertexFormat::kSint32x2:
      return {BaseType::kI32, 2};
    case VertexFormat::kSint32x3:
      return {BaseType::kI32, 3};
    case VertexFormat::kSint8x4:
    case VertexFormat::kSint16x4:
    case VertexFormat::kSint32x4:
      return {BaseType::kI32, 4};
    case VertexFormat::kFloat32:
      return {BaseType::kF32, 1};
    case VertexFormat::kUnorm8x2:
    case VertexFormat::kSnorm8x2:
    case VertexFormat::kUnorm16x2:
    case VertexFormat::kSnorm16x2:
    case VertexFormat::kFloat16x2:
    case VertexFormat::kFloat32x2:
      return {BaseType::kF32, 2};
    case VertexFormat::kFloat32x3:
      return {BaseType::kF32, 3};
    case VertexFormat::kUnorm8x4:
    case VertexFormat::kSnorm8x4:
    case VertexFormat::kUnorm16x4:
    case VertexFormat::kSnorm16x4:
    case VertexFormat::kFloat16x4:
    case VertexFormat::kFloat32x4:
      return {BaseType::kF32, 4};
  }
  return {BaseType::kInvalid, 0};
}

struct State {
  State(CloneContext& context, const VertexPulling::Config& c)
      : ctx(context), cfg(c) {}
  State(const State&) = default;
  ~State() = default;

  /// LocationReplacement describes an ast::Variable replacement for a
  /// location input.
  struct LocationReplacement {
    /// The variable to replace in the source Program
    ast::Variable* from;
    /// The replacement to use in the target ProgramBuilder
    ast::Variable* to;
  };

  struct LocationInfo {
    std::function<ast::Expression*()> expr;
    sem::Type* type;
  };

  CloneContext& ctx;
  VertexPulling::Config const cfg;
  std::unordered_map<uint32_t, LocationInfo> location_info;
  std::function<ast::Expression*()> vertex_index_expr = nullptr;
  std::function<ast::Expression*()> instance_index_expr = nullptr;
  Symbol pulling_position_name;
  Symbol struct_buffer_name;
  std::unordered_map<uint32_t, Symbol> vertex_buffer_names;
  ast::VariableList new_function_parameters;

  /// Generate the vertex buffer binding name
  /// @param index index to append to buffer name
  Symbol GetVertexBufferName(uint32_t index) {
    return utils::GetOrCreate(vertex_buffer_names, index, [&] {
      static const char kVertexBufferNamePrefix[] =
          "tint_pulling_vertex_buffer_";
      return ctx.dst->Symbols().New(kVertexBufferNamePrefix +
                                    std::to_string(index));
    });
  }

  /// Lazily generates the structure buffer symbol
  Symbol GetStructBufferName() {
    if (!struct_buffer_name.IsValid()) {
      static const char kStructBufferName[] = "tint_vertex_data";
      struct_buffer_name = ctx.dst->Symbols().New(kStructBufferName);
    }
    return struct_buffer_name;
  }

  /// Adds storage buffer decorated variables for the vertex buffers
  void AddVertexStorageBuffers() {
    // Creating the struct type
    static const char kStructName[] = "TintVertexData";
    auto* struct_type = ctx.dst->Structure(
        ctx.dst->Symbols().New(kStructName),
        {
            ctx.dst->Member(GetStructBufferName(),
                            ctx.dst->ty.array<ProgramBuilder::u32, 0>(4)),
        },
        {
            ctx.dst->create<ast::StructBlockDecoration>(),
        });
    for (uint32_t i = 0; i < cfg.vertex_state.size(); ++i) {
      // The decorated variable with struct type
      ctx.dst->Global(
          GetVertexBufferName(i), ctx.dst->ty.Of(struct_type),
          ast::StorageClass::kStorage, ast::Access::kRead,
          ast::DecorationList{
              ctx.dst->create<ast::BindingDecoration>(i),
              ctx.dst->create<ast::GroupDecoration>(cfg.pulling_group),
          });
    }
  }

  /// Creates and returns the assignment to the variables from the buffers
  ast::BlockStatement* CreateVertexPullingPreamble() {
    // Assign by looking at the vertex descriptor to find attributes with
    // matching location.

    ast::StatementList stmts;

    for (uint32_t buffer_idx = 0; buffer_idx < cfg.vertex_state.size();
         ++buffer_idx) {
      const VertexBufferLayoutDescriptor& buffer_layout =
          cfg.vertex_state[buffer_idx];

      if ((buffer_layout.array_stride & 3) != 0) {
        ctx.dst->Diagnostics().add_error(
            diag::System::Transform,
            "WebGPU requires that vertex stride must be a multiple of 4 bytes, "
            "but VertexPulling array stride for buffer " +
                std::to_string(buffer_idx) + " was " +
                std::to_string(buffer_layout.array_stride) + " bytes");
        return nullptr;
      }

      auto* index_expr = buffer_layout.step_mode == InputStepMode::kVertex
                             ? vertex_index_expr()
                             : instance_index_expr();

      // buffer_array_base is the base array offset for all the vertex
      // attributes. These are units of uint (4 bytes).
      auto buffer_array_base = ctx.dst->Symbols().New(
          "buffer_array_base_" + std::to_string(buffer_idx));

      auto* attribute_offset = index_expr;
      if (buffer_layout.array_stride != 4) {
        attribute_offset =
            ctx.dst->Mul(index_expr, buffer_layout.array_stride / 4u);
      }

      // let pulling_offset_n = <attribute_offset>
      stmts.emplace_back(ctx.dst->Decl(
          ctx.dst->Const(buffer_array_base, nullptr, attribute_offset)));

      for (const VertexAttributeDescriptor& attribute_desc :
           buffer_layout.attributes) {
        auto it = location_info.find(attribute_desc.shader_location);
        if (it == location_info.end()) {
          continue;
        }
        auto& var = it->second;

        // Data type of the target WGSL variable
        auto var_dt = DataTypeOf(var.type);
        // Data type of the vertex stream attribute
        auto fmt_dt = DataTypeOf(attribute_desc.format);

        // Base types must match between the vertex stream and the WGSL variable
        if (var_dt.base_type != fmt_dt.base_type) {
          std::stringstream err;
          err << "VertexAttributeDescriptor for location "
              << std::to_string(attribute_desc.shader_location)
              << " has format " << attribute_desc.format
              << " but shader expects "
              << var.type->FriendlyName(ctx.src->Symbols());
          ctx.dst->Diagnostics().add_error(diag::System::Transform, err.str());
          return nullptr;
        }

        // Load the attribute value
        auto* fetch = Fetch(buffer_array_base, attribute_desc.offset,
                            buffer_idx, attribute_desc.format);

        // The attribute value may not be of the desired vector width. If it is
        // not, we'll need to either reduce the width with a swizzle, or append
        // 0's and / or a 1.
        auto* value = fetch;
        if (var_dt.width < fmt_dt.width) {
          // WGSL variable vector width is smaller than the loaded vector width
          switch (var_dt.width) {
            case 1:
              value = ctx.dst->MemberAccessor(fetch, "x");
              break;
            case 2:
              value = ctx.dst->MemberAccessor(fetch, "xy");
              break;
            case 3:
              value = ctx.dst->MemberAccessor(fetch, "xyz");
              break;
            default:
              TINT_UNREACHABLE(Transform, ctx.dst->Diagnostics())
                  << var_dt.width;
              return nullptr;
          }
        } else if (var_dt.width > fmt_dt.width) {
          // WGSL variable vector width is wider than the loaded vector width
          ast::Type* ty = nullptr;
          ast::ExpressionList values{fetch};
          switch (var_dt.base_type) {
            case BaseType::kI32:
              ty = ctx.dst->ty.i32();
              for (uint32_t i = fmt_dt.width; i < var_dt.width; i++) {
                values.emplace_back(ctx.dst->Expr((i == 3) ? 1 : 0));
              }
              break;
            case BaseType::kU32:
              ty = ctx.dst->ty.u32();
              for (uint32_t i = fmt_dt.width; i < var_dt.width; i++) {
                values.emplace_back(ctx.dst->Expr((i == 3) ? 1u : 0u));
              }
              break;
            case BaseType::kF32:
              ty = ctx.dst->ty.f32();
              for (uint32_t i = fmt_dt.width; i < var_dt.width; i++) {
                values.emplace_back(ctx.dst->Expr((i == 3) ? 1.f : 0.f));
              }
              break;
            default:
              TINT_UNREACHABLE(Transform, ctx.dst->Diagnostics())
                  << var_dt.base_type;
              return nullptr;
          }
          value = ctx.dst->Construct(ctx.dst->ty.vec(ty, var_dt.width), values);
        }

        // Assign the value to the WGSL variable
        stmts.emplace_back(ctx.dst->Assign(var.expr(), value));
      }
    }

    if (stmts.empty()) {
      return nullptr;
    }

    return ctx.dst->create<ast::BlockStatement>(stmts);
  }

  /// Generates an expression reading from a buffer a specific format.
  /// @param array_base the symbol of the variable holding the base array offset
  /// of the vertex array (each index is 4-bytes).
  /// @param offset the byte offset of the data from `buffer_base`
  /// @param buffer the index of the vertex buffer
  /// @param format the format to read
  ast::Expression* Fetch(Symbol array_base,
                         uint32_t offset,
                         uint32_t buffer,
                         VertexFormat format) {
    using u32 = ProgramBuilder::u32;
    using i32 = ProgramBuilder::i32;
    using f32 = ProgramBuilder::f32;

    // Returns a u32 loaded from buffer_base + offset.
    auto load_u32 = [&] {
      return LoadPrimitive(array_base, offset, buffer, VertexFormat::kUint32);
    };

    // Returns a i32 loaded from buffer_base + offset.
    auto load_i32 = [&] { return ctx.dst->Bitcast<i32>(load_u32()); };

    // Returns a u32 loaded from buffer_base + offset + 4.
    auto load_next_u32 = [&] {
      return LoadPrimitive(array_base, offset + 4, buffer,
                           VertexFormat::kUint32);
    };

    // Returns a i32 loaded from buffer_base + offset + 4.
    auto load_next_i32 = [&] { return ctx.dst->Bitcast<i32>(load_next_u32()); };

    // Returns a u16 loaded from offset, packed in the high 16 bits of a u32.
    // The low 16 bits are 0.
    // `min_alignment` must be a power of two.
    // `offset` must be `min_alignment` bytes aligned.
    auto load_u16_h = [&] {
      auto low_u32_offset = offset & ~3u;
      auto* low_u32 = LoadPrimitive(array_base, low_u32_offset, buffer,
                                    VertexFormat::kUint32);
      switch (offset & 3) {
        case 0:
          return ctx.dst->Shl(low_u32, 16u);
        case 1:
          return ctx.dst->And(ctx.dst->Shl(low_u32, 8u), 0xffff0000u);
        case 2:
          return ctx.dst->And(low_u32, 0xffff0000u);
        default: {  // 3:
          auto* high_u32 = LoadPrimitive(array_base, low_u32_offset + 4, buffer,
                                         VertexFormat::kUint32);
          auto* shr = ctx.dst->Shr(low_u32, 8u);
          auto* shl = ctx.dst->Shl(high_u32, 24u);
          return ctx.dst->And(ctx.dst->Or(shl, shr), 0xffff0000u);
        }
      }
    };

    // Returns a u16 loaded from offset, packed in the low 16 bits of a u32.
    // The high 16 bits are 0.
    auto load_u16_l = [&] {
      auto low_u32_offset = offset & ~3u;
      auto* low_u32 = LoadPrimitive(array_base, low_u32_offset, buffer,
                                    VertexFormat::kUint32);
      switch (offset & 3) {
        case 0:
          return ctx.dst->And(low_u32, 0xffffu);
        case 1:
          return ctx.dst->And(ctx.dst->Shr(low_u32, 8u), 0xffffu);
        case 2:
          return ctx.dst->Shr(low_u32, 16u);
        default: {  // 3:
          auto* high_u32 = LoadPrimitive(array_base, low_u32_offset + 4, buffer,
                                         VertexFormat::kUint32);
          auto* shr = ctx.dst->Shr(low_u32, 24u);
          auto* shl = ctx.dst->Shl(high_u32, 8u);
          return ctx.dst->And(ctx.dst->Or(shl, shr), 0xffffu);
        }
      }
    };

    // Returns a i16 loaded from offset, packed in the high 16 bits of a u32.
    // The low 16 bits are 0.
    auto load_i16_h = [&] { return ctx.dst->Bitcast<i32>(load_u16_h()); };

    // Assumptions are made that alignment must be at least as large as the size
    // of a single component.
    switch (format) {
      // Basic primitives
      case VertexFormat::kUint32:
      case VertexFormat::kSint32:
      case VertexFormat::kFloat32:
        return LoadPrimitive(array_base, offset, buffer, format);

        // Vectors of basic primitives
      case VertexFormat::kUint32x2:
        return LoadVec(array_base, offset, buffer, 4, ctx.dst->ty.u32(),
                       VertexFormat::kUint32, 2);
      case VertexFormat::kUint32x3:
        return LoadVec(array_base, offset, buffer, 4, ctx.dst->ty.u32(),
                       VertexFormat::kUint32, 3);
      case VertexFormat::kUint32x4:
        return LoadVec(array_base, offset, buffer, 4, ctx.dst->ty.u32(),
                       VertexFormat::kUint32, 4);
      case VertexFormat::kSint32x2:
        return LoadVec(array_base, offset, buffer, 4, ctx.dst->ty.i32(),
                       VertexFormat::kSint32, 2);
      case VertexFormat::kSint32x3:
        return LoadVec(array_base, offset, buffer, 4, ctx.dst->ty.i32(),
                       VertexFormat::kSint32, 3);
      case VertexFormat::kSint32x4:
        return LoadVec(array_base, offset, buffer, 4, ctx.dst->ty.i32(),
                       VertexFormat::kSint32, 4);
      case VertexFormat::kFloat32x2:
        return LoadVec(array_base, offset, buffer, 4, ctx.dst->ty.f32(),
                       VertexFormat::kFloat32, 2);
      case VertexFormat::kFloat32x3:
        return LoadVec(array_base, offset, buffer, 4, ctx.dst->ty.f32(),
                       VertexFormat::kFloat32, 3);
      case VertexFormat::kFloat32x4:
        return LoadVec(array_base, offset, buffer, 4, ctx.dst->ty.f32(),
                       VertexFormat::kFloat32, 4);

      case VertexFormat::kUint8x2: {
        // yyxx0000, yyxx0000
        auto* u16s = ctx.dst->vec2<u32>(load_u16_h());
        // xx000000, yyxx0000
        auto* shl = ctx.dst->Shl(u16s, ctx.dst->vec2<u32>(8u, 0u));
        // 000000xx, 000000yy
        return ctx.dst->Shr(shl, ctx.dst->vec2<u32>(24u));
      }
      case VertexFormat::kUint8x4: {
        // wwzzyyxx, wwzzyyxx, wwzzyyxx, wwzzyyxx
        auto* u32s = ctx.dst->vec4<u32>(load_u32());
        // xx000000, yyxx0000, zzyyxx00, wwzzyyxx
        auto* shl = ctx.dst->Shl(u32s, ctx.dst->vec4<u32>(24u, 16u, 8u, 0u));
        // 000000xx, 000000yy, 000000zz, 000000ww
        return ctx.dst->Shr(shl, ctx.dst->vec4<u32>(24u));
      }
      case VertexFormat::kUint16x2: {
        // yyyyxxxx, yyyyxxxx
        auto* u32s = ctx.dst->vec2<u32>(load_u32());
        // xxxx0000, yyyyxxxx
        auto* shl = ctx.dst->Shl(u32s, ctx.dst->vec2<u32>(16u, 0u));
        // 0000xxxx, 0000yyyy
        return ctx.dst->Shr(shl, ctx.dst->vec2<u32>(16u));
      }
      case VertexFormat::kUint16x4: {
        // yyyyxxxx, wwwwzzzz
        auto* u32s = ctx.dst->vec2<u32>(load_u32(), load_next_u32());
        // yyyyxxxx, yyyyxxxx, wwwwzzzz, wwwwzzzz
        auto* xxyy = ctx.dst->MemberAccessor(u32s, "xxyy");
        // xxxx0000, yyyyxxxx, zzzz0000, wwwwzzzz
        auto* shl = ctx.dst->Shl(xxyy, ctx.dst->vec4<u32>(16u, 0u, 16u, 0u));
        // 0000xxxx, 0000yyyy, 0000zzzz, 0000wwww
        return ctx.dst->Shr(shl, ctx.dst->vec4<u32>(16u));
      }
      case VertexFormat::kSint8x2: {
        // yyxx0000, yyxx0000
        auto* i16s = ctx.dst->vec2<i32>(load_i16_h());
        // xx000000, yyxx0000
        auto* shl = ctx.dst->Shl(i16s, ctx.dst->vec2<u32>(8u, 0u));
        // ssssssxx, ssssssyy
        return ctx.dst->Shr(shl, ctx.dst->vec2<u32>(24u));
      }
      case VertexFormat::kSint8x4: {
        // wwzzyyxx, wwzzyyxx, wwzzyyxx, wwzzyyxx
        auto* i32s = ctx.dst->vec4<i32>(load_i32());
        // xx000000, yyxx0000, zzyyxx00, wwzzyyxx
        auto* shl = ctx.dst->Shl(i32s, ctx.dst->vec4<u32>(24u, 16u, 8u, 0u));
        // ssssssxx, ssssssyy, sssssszz, ssssssww
        return ctx.dst->Shr(shl, ctx.dst->vec4<u32>(24u));
      }
      case VertexFormat::kSint16x2: {
        // yyyyxxxx, yyyyxxxx
        auto* i32s = ctx.dst->vec2<i32>(load_i32());
        // xxxx0000, yyyyxxxx
        auto* shl = ctx.dst->Shl(i32s, ctx.dst->vec2<u32>(16u, 0u));
        // ssssxxxx, ssssyyyy
        return ctx.dst->Shr(shl, ctx.dst->vec2<u32>(16u));
      }
      case VertexFormat::kSint16x4: {
        // yyyyxxxx, wwwwzzzz
        auto* i32s = ctx.dst->vec2<i32>(load_i32(), load_next_i32());
        // yyyyxxxx, yyyyxxxx, wwwwzzzz, wwwwzzzz
        auto* xxyy = ctx.dst->MemberAccessor(i32s, "xxyy");
        // xxxx0000, yyyyxxxx, zzzz0000, wwwwzzzz
        auto* shl = ctx.dst->Shl(xxyy, ctx.dst->vec4<u32>(16u, 0u, 16u, 0u));
        // ssssxxxx, ssssyyyy, sssszzzz, sssswwww
        return ctx.dst->Shr(shl, ctx.dst->vec4<u32>(16u));
      }
      case VertexFormat::kUnorm8x2:
        return ctx.dst->MemberAccessor(
            ctx.dst->Call("unpack4x8unorm", load_u16_l()), "xy");
      case VertexFormat::kSnorm8x2:
        return ctx.dst->MemberAccessor(
            ctx.dst->Call("unpack4x8snorm", load_u16_l()), "xy");
      case VertexFormat::kUnorm8x4:
        return ctx.dst->Call("unpack4x8unorm", load_u32());
      case VertexFormat::kSnorm8x4:
        return ctx.dst->Call("unpack4x8snorm", load_u32());
      case VertexFormat::kUnorm16x2:
        return ctx.dst->Call("unpack2x16unorm", load_u32());
      case VertexFormat::kSnorm16x2:
        return ctx.dst->Call("unpack2x16snorm", load_u32());
      case VertexFormat::kFloat16x2:
        return ctx.dst->Call("unpack2x16float", load_u32());
      case VertexFormat::kUnorm16x4:
        return ctx.dst->vec4<f32>(
            ctx.dst->Call("unpack2x16unorm", load_u32()),
            ctx.dst->Call("unpack2x16unorm", load_next_u32()));
      case VertexFormat::kSnorm16x4:
        return ctx.dst->vec4<f32>(
            ctx.dst->Call("unpack2x16snorm", load_u32()),
            ctx.dst->Call("unpack2x16snorm", load_next_u32()));
      case VertexFormat::kFloat16x4:
        return ctx.dst->vec4<f32>(
            ctx.dst->Call("unpack2x16float", load_u32()),
            ctx.dst->Call("unpack2x16float", load_next_u32()));
    }

    TINT_UNREACHABLE(Transform, ctx.dst->Diagnostics())
        << "format " << static_cast<int>(format);
    return nullptr;
  }

  /// Generates an expression reading an aligned basic type (u32, i32, f32) from
  /// a vertex buffer.
  /// @param array_base the symbol of the variable holding the base array offset
  /// of the vertex array (each index is 4-bytes).
  /// @param offset the byte offset of the data from `buffer_base`
  /// @param buffer the index of the vertex buffer
  /// @param format VertexFormat::kUint32, VertexFormat::kSint32 or
  /// VertexFormat::kFloat32
  ast::Expression* LoadPrimitive(Symbol array_base,
                                 uint32_t offset,
                                 uint32_t buffer,
                                 VertexFormat format) {
    ast::Expression* u32 = nullptr;
    if ((offset & 3) == 0) {
      // Aligned load.

      ast ::Expression* index = nullptr;
      if (offset > 0) {
        index = ctx.dst->Add(array_base, offset / 4);
      } else {
        index = ctx.dst->Expr(array_base);
      }
      u32 = ctx.dst->IndexAccessor(
          ctx.dst->MemberAccessor(GetVertexBufferName(buffer),
                                  GetStructBufferName()),
          index);

    } else {
      // Unaligned load
      uint32_t offset_aligned = offset & ~3u;
      auto* low = LoadPrimitive(array_base, offset_aligned, buffer,
                                VertexFormat::kUint32);
      auto* high = LoadPrimitive(array_base, offset_aligned + 4u, buffer,
                                 VertexFormat::kUint32);

      uint32_t shift = 8u * (offset & 3u);

      auto* low_shr = ctx.dst->Shr(low, shift);
      auto* high_shl = ctx.dst->Shl(high, 32u - shift);
      u32 = ctx.dst->Or(low_shr, high_shl);
    }

    switch (format) {
      case VertexFormat::kUint32:
        return u32;
      case VertexFormat::kSint32:
        return ctx.dst->Bitcast(ctx.dst->ty.i32(), u32);
      case VertexFormat::kFloat32:
        return ctx.dst->Bitcast(ctx.dst->ty.f32(), u32);
      default:
        break;
    }
    TINT_UNREACHABLE(Transform, ctx.dst->Diagnostics())
        << "invalid format for LoadPrimitive" << static_cast<int>(format);
    return nullptr;
  }

  /// Generates an expression reading a vec2/3/4 from a vertex buffer.
  /// @param array_base the symbol of the variable holding the base array offset
  /// of the vertex array (each index is 4-bytes).
  /// @param offset the byte offset of the data from `buffer_base`
  /// @param buffer the index of the vertex buffer
  /// @param element_stride stride between elements, in bytes
  /// @param base_type underlying AST type
  /// @param base_format underlying vertex format
  /// @param count how many elements the vector has
  ast::Expression* LoadVec(Symbol array_base,
                           uint32_t offset,
                           uint32_t buffer,
                           uint32_t element_stride,
                           ast::Type* base_type,
                           VertexFormat base_format,
                           uint32_t count) {
    ast::ExpressionList expr_list;
    for (uint32_t i = 0; i < count; ++i) {
      // Offset read position by element_stride for each component
      uint32_t primitive_offset = offset + element_stride * i;
      expr_list.push_back(
          LoadPrimitive(array_base, primitive_offset, buffer, base_format));
    }

    return ctx.dst->create<ast::TypeConstructorExpression>(
        ctx.dst->create<ast::Vector>(base_type, count), std::move(expr_list));
  }

  /// Process a non-struct entry point parameter.
  /// Generate function-scope variables for location parameters, and record
  /// vertex_index and instance_index builtins if present.
  /// @param func the entry point function
  /// @param param the parameter to process
  void ProcessNonStructParameter(ast::Function* func, ast::Variable* param) {
    if (auto* location =
            ast::GetDecoration<ast::LocationDecoration>(param->decorations())) {
      // Create a function-scope variable to replace the parameter.
      auto func_var_sym = ctx.Clone(param->symbol());
      auto* func_var_type = ctx.Clone(param->type());
      auto* func_var = ctx.dst->Var(func_var_sym, func_var_type);
      ctx.InsertFront(func->body()->statements(), ctx.dst->Decl(func_var));
      // Capture mapping from location to the new variable.
      LocationInfo info;
      info.expr = [this, func_var]() { return ctx.dst->Expr(func_var); };
      info.type = ctx.src->Sem().Get(param)->Type();
      location_info[location->value()] = info;
    } else if (auto* builtin = ast::GetDecoration<ast::BuiltinDecoration>(
                   param->decorations())) {
      // Check for existing vertex_index and instance_index builtins.
      if (builtin->value() == ast::Builtin::kVertexIndex) {
        vertex_index_expr = [this, param]() {
          return ctx.dst->Expr(ctx.Clone(param->symbol()));
        };
      } else if (builtin->value() == ast::Builtin::kInstanceIndex) {
        instance_index_expr = [this, param]() {
          return ctx.dst->Expr(ctx.Clone(param->symbol()));
        };
      }
      new_function_parameters.push_back(ctx.Clone(param));
    } else {
      TINT_ICE(Transform, ctx.dst->Diagnostics())
          << "Invalid entry point parameter";
    }
  }

  /// Process a struct entry point parameter.
  /// If the struct has members with location attributes, push the parameter to
  /// a function-scope variable and create a new struct parameter without those
  /// attributes. Record expressions for members that are vertex_index and
  /// instance_index builtins.
  /// @param func the entry point function
  /// @param param the parameter to process
  /// @param struct_ty the structure type
  void ProcessStructParameter(ast::Function* func,
                              ast::Variable* param,
                              const ast::Struct* struct_ty) {
    auto param_sym = ctx.Clone(param->symbol());

    // Process the struct members.
    bool has_locations = false;
    ast::StructMemberList members_to_clone;
    for (auto* member : struct_ty->members()) {
      auto member_sym = ctx.Clone(member->symbol());
      std::function<ast::Expression*()> member_expr = [this, param_sym,
                                                       member_sym]() {
        return ctx.dst->MemberAccessor(param_sym, member_sym);
      };

      if (auto* location = ast::GetDecoration<ast::LocationDecoration>(
              member->decorations())) {
        // Capture mapping from location to struct member.
        LocationInfo info;
        info.expr = member_expr;
        info.type = ctx.src->Sem().Get(member)->Type();
        location_info[location->value()] = info;
        has_locations = true;
      } else if (auto* builtin = ast::GetDecoration<ast::BuiltinDecoration>(
                     member->decorations())) {
        // Check for existing vertex_index and instance_index builtins.
        if (builtin->value() == ast::Builtin::kVertexIndex) {
          vertex_index_expr = member_expr;
        } else if (builtin->value() == ast::Builtin::kInstanceIndex) {
          instance_index_expr = member_expr;
        }
        members_to_clone.push_back(member);
      } else {
        TINT_ICE(Transform, ctx.dst->Diagnostics())
            << "Invalid entry point parameter";
      }
    }

    if (!has_locations) {
      // Nothing to do.
      new_function_parameters.push_back(ctx.Clone(param));
      return;
    }

    // Create a function-scope variable to replace the parameter.
    auto* func_var = ctx.dst->Var(param_sym, ctx.Clone(param->type()));
    ctx.InsertFront(func->body()->statements(), ctx.dst->Decl(func_var));

    if (!members_to_clone.empty()) {
      // Create a new struct without the location attributes.
      ast::StructMemberList new_members;
      for (auto* member : members_to_clone) {
        auto member_sym = ctx.Clone(member->symbol());
        auto* member_type = ctx.Clone(member->type());
        auto member_decos = ctx.Clone(member->decorations());
        new_members.push_back(
            ctx.dst->Member(member_sym, member_type, std::move(member_decos)));
      }
      auto* new_struct = ctx.dst->Structure(ctx.dst->Sym(), new_members);

      // Create a new function parameter with this struct.
      auto* new_param =
          ctx.dst->Param(ctx.dst->Sym(), ctx.dst->ty.Of(new_struct));
      new_function_parameters.push_back(new_param);

      // Copy values from the new parameter to the function-scope variable.
      for (auto* member : members_to_clone) {
        auto member_name = ctx.Clone(member->symbol());
        ctx.InsertFront(
            func->body()->statements(),
            ctx.dst->Assign(ctx.dst->MemberAccessor(func_var, member_name),
                            ctx.dst->MemberAccessor(new_param, member_name)));
      }
    }
  }

  /// Process an entry point function.
  /// @param func the entry point function
  void Process(ast::Function* func) {
    if (func->body()->empty()) {
      return;
    }

    // Process entry point parameters.
    for (auto* param : func->params()) {
      auto* sem = ctx.src->Sem().Get(param);
      if (auto* str = sem->Type()->As<sem::Struct>()) {
        ProcessStructParameter(func, param, str->Declaration());
      } else {
        ProcessNonStructParameter(func, param);
      }
    }

    // Insert new parameters for vertex_index and instance_index if needed.
    if (!vertex_index_expr) {
      for (const VertexBufferLayoutDescriptor& layout : cfg.vertex_state) {
        if (layout.step_mode == InputStepMode::kVertex) {
          auto name = ctx.dst->Symbols().New("tint_pulling_vertex_index");
          new_function_parameters.push_back(
              ctx.dst->Param(name, ctx.dst->ty.u32(),
                             {ctx.dst->Builtin(ast::Builtin::kVertexIndex)}));
          vertex_index_expr = [this, name]() { return ctx.dst->Expr(name); };
          break;
        }
      }
    }
    if (!instance_index_expr) {
      for (const VertexBufferLayoutDescriptor& layout : cfg.vertex_state) {
        if (layout.step_mode == InputStepMode::kInstance) {
          auto name = ctx.dst->Symbols().New("tint_pulling_instance_index");
          new_function_parameters.push_back(
              ctx.dst->Param(name, ctx.dst->ty.u32(),
                             {ctx.dst->Builtin(ast::Builtin::kInstanceIndex)}));
          instance_index_expr = [this, name]() { return ctx.dst->Expr(name); };
          break;
        }
      }
    }

    // Generate vertex pulling preamble.
    if (auto* block = CreateVertexPullingPreamble()) {
      ctx.InsertFront(func->body()->statements(), block);
    }

    // Rewrite the function header with the new parameters.
    auto func_sym = ctx.Clone(func->symbol());
    auto* ret_type = ctx.Clone(func->return_type());
    auto* body = ctx.Clone(func->body());
    auto decos = ctx.Clone(func->decorations());
    auto ret_decos = ctx.Clone(func->return_type_decorations());
    auto* new_func = ctx.dst->create<ast::Function>(
        func->source(), func_sym, new_function_parameters, ret_type, body,
        std::move(decos), std::move(ret_decos));
    ctx.Replace(func, new_func);
  }
};

}  // namespace

VertexPulling::VertexPulling() = default;
VertexPulling::~VertexPulling() = default;

void VertexPulling::Run(CloneContext& ctx, const DataMap& inputs, DataMap&) {
  auto cfg = cfg_;
  if (auto* cfg_data = inputs.Get<Config>()) {
    cfg = *cfg_data;
  }

  // Find entry point
  auto* func = ctx.src->AST().Functions().Find(
      ctx.src->Symbols().Get(cfg.entry_point_name),
      ast::PipelineStage::kVertex);
  if (func == nullptr) {
    ctx.dst->Diagnostics().add_error(diag::System::Transform,
                                     "Vertex stage entry point not found");
    return;
  }

  // TODO(idanr): Need to check shader locations in descriptor cover all
  // attributes

  // TODO(idanr): Make sure we covered all error cases, to guarantee the
  // following stages will pass

  State state{ctx, cfg};
  state.AddVertexStorageBuffers();
  state.Process(func);

  ctx.Clone();
}

VertexPulling::Config::Config() = default;
VertexPulling::Config::Config(const Config&) = default;
VertexPulling::Config::~Config() = default;
VertexPulling::Config& VertexPulling::Config::operator=(const Config&) =
    default;

VertexBufferLayoutDescriptor::VertexBufferLayoutDescriptor() = default;

VertexBufferLayoutDescriptor::VertexBufferLayoutDescriptor(
    uint32_t in_array_stride,
    InputStepMode in_step_mode,
    std::vector<VertexAttributeDescriptor> in_attributes)
    : array_stride(in_array_stride),
      step_mode(in_step_mode),
      attributes(std::move(in_attributes)) {}

VertexBufferLayoutDescriptor::VertexBufferLayoutDescriptor(
    const VertexBufferLayoutDescriptor& other) = default;

VertexBufferLayoutDescriptor& VertexBufferLayoutDescriptor::operator=(
    const VertexBufferLayoutDescriptor& other) = default;

VertexBufferLayoutDescriptor::~VertexBufferLayoutDescriptor() = default;

}  // namespace transform
}  // namespace tint
