// Copyright 2021 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.

#ifndef SRC_TRANSFORM_CANONICALIZE_ENTRY_POINT_IO_H_
#define SRC_TRANSFORM_CANONICALIZE_ENTRY_POINT_IO_H_

#include "src/transform/transform.h"

namespace tint {
namespace transform {

/// CanonicalizeEntryPointIO is a transform used to rewrite shader entry point
/// interfaces into a form that the generators can handle. Each entry point
/// function is stripped of all shader IO attributes and wrapped in a function
/// that provides the shader interface.
/// The transform config determines whether to use global variables, structures,
/// or parameters for the shader inputs and outputs, and optionally adds
/// additional builtins to the shader interface.
///
/// Before:
/// ```
/// struct Locations{
///   [[location(1)]] loc1 : f32;
///   [[location(2)]] loc2 : vec4<u32>;
/// };
///
/// [[stage(fragment)]]
/// fn frag_main([[builtin(position)]] coord : vec4<f32>,
///              locations : Locations) -> [[location(0)]] f32 {
///   if (coord.w > 1.0) {
///     return 0.0;
///   }
///   var col : f32 = (coord.x * locations.loc1);
///   return col;
/// }
/// ```
///
/// After (using structures for all parameters):
/// ```
/// struct Locations{
///   loc1 : f32;
///   loc2 : vec4<u32>;
/// };
///
/// struct frag_main_in {
///   [[builtin(position)]] coord : vec4<f32>;
///   [[location(1)]] loc1 : f32;
///   [[location(2)]] loc2 : vec4<u32>
/// };
///
/// struct frag_main_out {
///   [[location(0)]] loc0 : f32;
/// };
///
/// fn frag_main_inner(coord : vec4<f32>,
///                    locations : Locations) -> f32 {
///   if (coord.w > 1.0) {
///     return 0.0;
///   }
///   var col : f32 = (coord.x * locations.loc1);
///   return col;
/// }
///
/// [[stage(fragment)]]
/// fn frag_main(in : frag_main_in) -> frag_main_out {
///   let inner_retval = frag_main_inner(in.coord, Locations(in.loc1, in.loc2));
///   var wrapper_result : frag_main_out;
///   wrapper_result.loc0 = inner_retval;
///   return wrapper_result;
/// }
/// ```
class CanonicalizeEntryPointIO
    : public Castable<CanonicalizeEntryPointIO, Transform> {
 public:
  /// ShaderStyle is an enumerator of different ways to emit shader IO.
  enum class ShaderStyle {
    /// Target SPIR-V (using global variables).
    kSpirv,
    /// Target MSL (using non-struct function parameters for builtins).
    kMsl,
    /// Target HLSL (using structures for all IO).
    kHlsl,
  };

  /// Configuration options for the transform.
  struct Config : public Castable<Config, Data> {
    /// Constructor
    /// @param style the approach to use for emitting shader IO.
    /// @param sample_mask an optional sample mask to combine with shader masks
    /// @param emit_vertex_point_size `true` to generate a pointsize builtin
    explicit Config(ShaderStyle style,
                    uint32_t sample_mask = 0xFFFFFFFF,
                    bool emit_vertex_point_size = false);

    /// Copy constructor
    Config(const Config&);

    /// Destructor
    ~Config() override;

    /// The approach to use for emitting shader IO.
    const ShaderStyle shader_style;

    /// A fixed sample mask to combine into masks produced by fragment shaders.
    const uint32_t fixed_sample_mask;

    /// Set to `true` to generate a pointsize builtin and have it set to 1.0
    /// from all vertex shaders in the module.
    const bool emit_vertex_point_size;
  };

  /// Constructor
  CanonicalizeEntryPointIO();
  ~CanonicalizeEntryPointIO() override;

 protected:
  /// Runs the transform using the CloneContext built for transforming a
  /// program. Run() is responsible for calling Clone() on the CloneContext.
  /// @param ctx the CloneContext primed with the input program and
  /// ProgramBuilder
  /// @param inputs optional extra transform-specific input data
  /// @param outputs optional extra transform-specific output data
  void Run(CloneContext& ctx, const DataMap& inputs, DataMap& outputs) override;

  struct State;
};

}  // namespace transform
}  // namespace tint

#endif  // SRC_TRANSFORM_CANONICALIZE_ENTRY_POINT_IO_H_
