// Copyright 2022 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/combine_samplers.h"

#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

#include "src/sem/function.h"
#include "src/sem/statement.h"

#include "src/utils/map.h"

TINT_INSTANTIATE_TYPEINFO(tint::transform::CombineSamplers);
TINT_INSTANTIATE_TYPEINFO(tint::transform::CombineSamplers::BindingInfo);

namespace {

bool IsGlobal(const tint::sem::VariablePair& pair) {
  return pair.first->Is<tint::sem::GlobalVariable>() &&
         (!pair.second || pair.second->Is<tint::sem::GlobalVariable>());
}

}  // namespace

namespace tint {
namespace transform {

CombineSamplers::BindingInfo::BindingInfo(const BindingMap& map)
    : binding_map(map) {}
CombineSamplers::BindingInfo::BindingInfo(const BindingInfo& other) = default;
CombineSamplers::BindingInfo::~BindingInfo() = default;

/// The PIMPL state for the CombineSamplers transform
struct CombineSamplers::State {
  /// The clone context
  CloneContext& ctx;

  /// The binding info
  const BindingInfo* binding_info;

  /// Map from a texture/sampler pair to the corresponding combined sampler
  /// variable
  using CombinedTextureSamplerMap =
      std::unordered_map<sem::VariablePair, const ast::Variable*>;

  /// Use sem::BindingPoint without scope.
  using BindingPoint = sem::BindingPoint;

  /// A map of all global texture/sampler variable pairs to the global
  /// combined sampler variable that will replace it.
  CombinedTextureSamplerMap global_combined_texture_samplers_;

  /// A map of all texture/sampler variable pairs that contain a function
  /// parameter to the combined sampler function paramter that will replace it.
  std::unordered_map<const sem::Function*, CombinedTextureSamplerMap>
      function_combined_texture_samplers_;

  /// Placeholder global samplers used when a function contains texture-only
  /// references (one comparison sampler, one regular). These are also used as
  /// temporary sampler parameters to the texture intrinsics to satsify the WGSL
  /// resolver, but are then ignored and removed by the GLSL writer.
  const ast::Variable* placeholder_samplers_[2] = {};

  /// Group and binding decorations used by all combined sampler globals.
  /// Group 0 and binding 0 are used, with collisions disabled.
  /// @returns the newly-created decoration list
  ast::DecorationList Decorations() const {
    auto decorations = ctx.dst->GroupAndBinding(0, 0);
    decorations.push_back(
        ctx.dst->Disable(ast::DisabledValidation::kBindingPointCollision));
    return decorations;
  }

  /// Constructor
  /// @param context the clone context
  /// @param info the binding map information
  State(CloneContext& context, const BindingInfo* info)
      : ctx(context), binding_info(info) {}

  /// Creates a combined sampler global variables.
  /// (Note this is actually a Texture node at the AST level, but it will be
  /// written as the corresponding sampler (eg., sampler2D) on GLSL output.)
  /// @param texture_var the texture (global) variable
  /// @param sampler_var the sampler (global) variable
  /// @param name the default name to use (may be overridden by map lookup)
  /// @returns the newly-created global variable
  const ast::Variable* CreateCombinedGlobal(const sem::Variable* texture_var,
                                            const sem::Variable* sampler_var,
                                            std::string name) {
    SamplerTexturePair bp_pair;
    bp_pair.texture_binding_point =
        texture_var->As<sem::GlobalVariable>()->BindingPoint();
    bp_pair.sampler_binding_point =
        sampler_var ? sampler_var->As<sem::GlobalVariable>()->BindingPoint()
                    : BindingPoint();
    auto it = binding_info->binding_map.find(bp_pair);
    if (it != binding_info->binding_map.end()) {
      name = it->second;
    }
    const ast::Type* type = CreateASTTypeFor(ctx, texture_var->Type());
    Symbol symbol = ctx.dst->Symbols().New(name);
    return ctx.dst->Global(symbol, type, Decorations());
  }

  /// Creates placeholder global sampler variables.
  /// @param kind the sampler kind to create for
  /// @returns the newly-created global variable
  const ast::Variable* CreatePlaceholder(ast::SamplerKind kind) {
    const ast::Type* type = ctx.dst->ty.sampler(kind);
    const char* name = kind == ast::SamplerKind::kComparisonSampler
                           ? "placeholder_comparison_sampler"
                           : "placeholder_sampler";
    Symbol symbol = ctx.dst->Symbols().New(name);
    return ctx.dst->Global(symbol, type, Decorations());
  }

  /// Performs the transformation
  void Run() {
    auto& sem = ctx.src->Sem();

    // Remove all texture and sampler global variables. These will be replaced
    // by combined samplers.
    for (auto* var : ctx.src->AST().GlobalVariables()) {
      auto* type = sem.Get(var->type);
      if (type && type->IsAnyOf<sem::Texture, sem::Sampler>()) {
        ctx.Remove(ctx.src->AST().GlobalDeclarations(), var);
      } else if (auto binding_point = var->BindingPoint()) {
        if (binding_point.group->value == 0 &&
            binding_point.binding->value == 0) {
          auto* decoration =
              ctx.dst->Disable(ast::DisabledValidation::kBindingPointCollision);
          ctx.InsertFront(var->decorations, decoration);
        }
      }
    }

    // Rewrite all function signatures to use combined samplers, and remove
    // separate textures & samplers. Create new combined globals where found.
    ctx.ReplaceAll([&](const ast::Function* src) -> const ast::Function* {
      if (auto* func = sem.Get(src)) {
        auto pairs = func->TextureSamplerPairs();
        if (pairs.empty()) {
          return nullptr;
        }
        ast::VariableList params;
        for (auto pair : func->TextureSamplerPairs()) {
          const sem::Variable* texture_var = pair.first;
          const sem::Variable* sampler_var = pair.second;
          std::string name =
              ctx.src->Symbols().NameFor(texture_var->Declaration()->symbol);
          if (sampler_var) {
            name += "_" + ctx.src->Symbols().NameFor(
                              sampler_var->Declaration()->symbol);
          }
          if (IsGlobal(pair)) {
            // Both texture and sampler are global; add a new global variable
            // to represent the combined sampler (if not already created).
            utils::GetOrCreate(global_combined_texture_samplers_, pair, [&] {
              return CreateCombinedGlobal(texture_var, sampler_var, name);
            });
          } else {
            // Either texture or sampler (or both) is a function parameter;
            // add a new function parameter to represent the combined sampler.
            const ast::Type* type = CreateASTTypeFor(ctx, texture_var->Type());
            const ast::Variable* var =
                ctx.dst->Param(ctx.dst->Symbols().New(name), type);
            params.push_back(var);
            function_combined_texture_samplers_[func][pair] = var;
          }
        }
        // Filter out separate textures and samplers from the original
        // function signature.
        for (auto* var : src->params) {
          if (!sem.Get(var->type)->IsAnyOf<sem::Texture, sem::Sampler>()) {
            params.push_back(ctx.Clone(var));
          }
        }
        // Create a new function signature that differs only in the parameter
        // list.
        auto symbol = ctx.Clone(src->symbol);
        auto* return_type = ctx.Clone(src->return_type);
        auto* body = ctx.Clone(src->body);
        auto decorations = ctx.Clone(src->decorations);
        auto return_type_decorations = ctx.Clone(src->return_type_decorations);
        return ctx.dst->create<ast::Function>(
            symbol, params, return_type, body, std::move(decorations),
            std::move(return_type_decorations));
      }
      return nullptr;
    });

    // Replace all function call expressions containing texture or
    // sampler parameters to use the current function's combined samplers or
    // the combined global samplers, as appropriate.
    ctx.ReplaceAll([&](const ast::CallExpression* expr)
                       -> const ast::Expression* {
      if (auto* call = sem.Get(expr)) {
        ast::ExpressionList args;
        // Replace all texture intrinsic calls.
        if (auto* intrinsic = call->Target()->As<sem::Intrinsic>()) {
          const auto& signature = intrinsic->Signature();
          int sampler_index = signature.IndexOf(sem::ParameterUsage::kSampler);
          int texture_index = signature.IndexOf(sem::ParameterUsage::kTexture);
          if (texture_index == -1) {
            return nullptr;
          }
          const sem::Expression* texture = call->Arguments()[texture_index];
          const sem::Expression* sampler =
              sampler_index != -1 ? call->Arguments()[sampler_index] : nullptr;
          auto* texture_var = texture->As<sem::VariableUser>()->Variable();
          auto* sampler_var =
              sampler ? sampler->As<sem::VariableUser>()->Variable() : nullptr;
          sem::VariablePair new_pair(texture_var, sampler_var);
          for (auto* arg : expr->args) {
            auto* type = ctx.src->TypeOf(arg)->UnwrapRef();
            if (type->Is<sem::Texture>()) {
              const ast::Variable* var =
                  IsGlobal(new_pair)
                      ? global_combined_texture_samplers_[new_pair]
                      : function_combined_texture_samplers_
                            [call->Stmt()->Function()][new_pair];
              args.push_back(ctx.dst->Expr(var->symbol));
            } else if (auto* sampler_type = type->As<sem::Sampler>()) {
              ast::SamplerKind kind = sampler_type->kind();
              int index = (kind == ast::SamplerKind::kSampler) ? 0 : 1;
              const ast::Variable*& p = placeholder_samplers_[index];
              if (!p) {
                p = CreatePlaceholder(kind);
              }
              args.push_back(ctx.dst->Expr(p->symbol));
            } else {
              args.push_back(ctx.Clone(arg));
            }
          }
          return ctx.dst->Call(ctx.Clone(expr->target.name), args);
        }
        // Replace all function calls.
        if (auto* callee = call->Target()->As<sem::Function>()) {
          for (auto pair : callee->TextureSamplerPairs()) {
            // Global pairs used by the callee do not require a function
            // parameter at the call site.
            if (IsGlobal(pair)) {
              continue;
            }
            const sem::Variable* texture_var = pair.first;
            const sem::Variable* sampler_var = pair.second;
            if (auto* param = texture_var->As<sem::Parameter>()) {
              const sem::Expression* texture =
                  call->Arguments()[param->Index()];
              texture_var = texture->As<sem::VariableUser>()->Variable();
            }
            if (sampler_var) {
              if (auto* param = sampler_var->As<sem::Parameter>()) {
                const sem::Expression* sampler =
                    call->Arguments()[param->Index()];
                sampler_var = sampler->As<sem::VariableUser>()->Variable();
              }
            }
            sem::VariablePair new_pair(texture_var, sampler_var);
            // If both texture and sampler are (now) global, pass that
            // global variable to the callee. Otherwise use the caller's
            // function parameter for this pair.
            const ast::Variable* var =
                IsGlobal(new_pair) ? global_combined_texture_samplers_[new_pair]
                                   : function_combined_texture_samplers_
                                         [call->Stmt()->Function()][new_pair];
            auto* arg = ctx.dst->Expr(var->symbol);
            args.push_back(arg);
          }
          // Append all of the remaining non-texture and non-sampler
          // parameters.
          for (auto* arg : expr->args) {
            if (!ctx.src->TypeOf(arg)
                     ->UnwrapRef()
                     ->IsAnyOf<sem::Texture, sem::Sampler>()) {
              args.push_back(ctx.Clone(arg));
            }
          }
          return ctx.dst->Call(ctx.Clone(expr->target.name), args);
        }
      }
      return nullptr;
    });

    ctx.Clone();
  }
};

CombineSamplers::CombineSamplers() = default;

CombineSamplers::~CombineSamplers() = default;

void CombineSamplers::Run(CloneContext& ctx,
                          const DataMap& inputs,
                          DataMap&) const {
  auto* binding_info = inputs.Get<BindingInfo>();
  if (!binding_info) {
    ctx.dst->Diagnostics().add_error(
        diag::System::Transform,
        "missing transform data for " + std::string(TypeInfo().name));
    return;
  }

  State(ctx, binding_info).Run();
}

}  // namespace transform
}  // namespace tint
