// 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->size()};
  }
  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::kU32);
    };

    // 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::kU32);
    };

    // 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::kU32);
      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::kU32);
          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::kU32);
      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::kU32);
          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::kU32, 2);
      case VertexFormat::kUint32x3:
        return LoadVec(array_base, offset, buffer, 4, ctx.dst->ty.u32(),
                       VertexFormat::kU32, 3);
      case VertexFormat::kUint32x4:
        return LoadVec(array_base, offset, buffer, 4, ctx.dst->ty.u32(),
                       VertexFormat::kU32, 4);
      case VertexFormat::kSint32x2:
        return LoadVec(array_base, offset, buffer, 4, ctx.dst->ty.i32(),
                       VertexFormat::kI32, 2);
      case VertexFormat::kSint32x3:
        return LoadVec(array_base, offset, buffer, 4, ctx.dst->ty.i32(),
                       VertexFormat::kI32, 3);
      case VertexFormat::kSint32x4:
        return LoadVec(array_base, offset, buffer, 4, ctx.dst->ty.i32(),
                       VertexFormat::kI32, 4);
      case VertexFormat::kFloat32x2:
        return LoadVec(array_base, offset, buffer, 4, ctx.dst->ty.f32(),
                       VertexFormat::kF32, 2);
      case VertexFormat::kFloat32x3:
        return LoadVec(array_base, offset, buffer, 4, ctx.dst->ty.f32(),
                       VertexFormat::kF32, 3);
      case VertexFormat::kFloat32x4:
        return LoadVec(array_base, offset, buffer, 4, ctx.dst->ty.f32(),
                       VertexFormat::kF32, 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::kU32, VertexFormat::kI32 or VertexFormat::kF32
  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::kU32);
      auto* high = LoadPrimitive(array_base, offset_aligned + 4u, buffer,
                                 VertexFormat::kU32);

      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::kU32:
        return u32;
      case VertexFormat::kI32:
        return ctx.dst->Bitcast(ctx.dst->ty.i32(), u32);
      case VertexFormat::kF32:
        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
