// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef FLUTTER_IMPELLER_RENDERER_PIPELINE_H_
#define FLUTTER_IMPELLER_RENDERER_PIPELINE_H_

#include <future>

#include "compute_pipeline_descriptor.h"
#include "impeller/renderer/compute_pipeline_builder.h"
#include "impeller/renderer/compute_pipeline_descriptor.h"
#include "impeller/renderer/context.h"
#include "impeller/renderer/pipeline_builder.h"
#include "impeller/renderer/pipeline_descriptor.h"
#include "impeller/renderer/shader_stage_compatibility_checker.h"

namespace impeller {

class PipelineLibrary;
template <typename PipelineDescriptor_>
class Pipeline;

template <typename T>
struct PipelineFuture {
  std::optional<T> descriptor;
  std::shared_future<std::shared_ptr<Pipeline<T>>> future;

  const std::shared_ptr<Pipeline<T>> Get() const { return future.get(); }

  bool IsValid() const { return future.valid(); }
};

//------------------------------------------------------------------------------
/// @brief      Describes the fixed function and programmable aspects of
///             rendering and compute operations performed by commands submitted
///             to the GPU via a command buffer.
///
///             A pipeline handle must be allocated upfront and kept alive for
///             as long as possible. Do not create a pipeline object within a
///             frame workload.
///
///             This pipeline object is almost never used directly as it is
///             untyped. Use reflected shader information generated by the
///             Impeller offline shader compiler to generate a typed pipeline
///             object.
///
template <typename T>
class Pipeline {
 public:
  virtual ~Pipeline();

  virtual bool IsValid() const = 0;

  //----------------------------------------------------------------------------
  /// @brief      Get the descriptor that was responsible for creating this
  ///             pipeline. It may be copied and modified to create a pipeline
  ///             variant.
  ///
  /// @return     The descriptor.
  ///
  const T& GetDescriptor() const;

  PipelineFuture<T> CreateVariant(
      std::function<void(T& desc)> descriptor_callback) const;

 protected:
  const std::weak_ptr<PipelineLibrary> library_;

  const T desc_;

  Pipeline(std::weak_ptr<PipelineLibrary> library, T desc);

 private:
  Pipeline(const Pipeline&) = delete;

  Pipeline& operator=(const Pipeline&) = delete;
};

extern template class Pipeline<PipelineDescriptor>;
extern template class Pipeline<ComputePipelineDescriptor>;

PipelineFuture<PipelineDescriptor> CreatePipelineFuture(
    const Context& context,
    std::optional<PipelineDescriptor> desc);

PipelineFuture<ComputePipelineDescriptor> CreatePipelineFuture(
    const Context& context,
    std::optional<ComputePipelineDescriptor> desc);

template <class VertexShader_, class FragmentShader_>
class RenderPipelineT {
  static_assert(
      ShaderStageCompatibilityChecker<VertexShader_, FragmentShader_>::Check(),
      "The output slots for the fragment shader don't have matches in the "
      "vertex shader's output slots. This will result in a linker error.");

 public:
  using VertexShader = VertexShader_;
  using FragmentShader = FragmentShader_;
  using Builder = PipelineBuilder<VertexShader, FragmentShader>;

  explicit RenderPipelineT(const Context& context)
      : RenderPipelineT(CreatePipelineFuture(
            context,
            Builder::MakeDefaultPipelineDescriptor(context))) {}

  explicit RenderPipelineT(const Context& context,
                           std::optional<PipelineDescriptor> desc)
      : RenderPipelineT(CreatePipelineFuture(context, desc)) {}

  explicit RenderPipelineT(PipelineFuture<PipelineDescriptor> future)
      : pipeline_future_(std::move(future)) {}

  std::shared_ptr<Pipeline<PipelineDescriptor>> WaitAndGet() {
    if (did_wait_) {
      return pipeline_;
    }
    did_wait_ = true;
    if (pipeline_future_.IsValid()) {
      pipeline_ = pipeline_future_.Get();
    }
    return pipeline_;
  }

  std::optional<PipelineDescriptor> GetDescriptor() const {
    return pipeline_future_.descriptor;
  }

 private:
  PipelineFuture<PipelineDescriptor> pipeline_future_;
  std::shared_ptr<Pipeline<PipelineDescriptor>> pipeline_;
  bool did_wait_ = false;

  RenderPipelineT(const RenderPipelineT&) = delete;

  RenderPipelineT& operator=(const RenderPipelineT&) = delete;
};

template <class ComputeShader_>
class ComputePipelineT {
 public:
  using ComputeShader = ComputeShader_;
  using Builder = ComputePipelineBuilder<ComputeShader>;

  explicit ComputePipelineT(const Context& context)
      : ComputePipelineT(CreatePipelineFuture(
            context,
            Builder::MakeDefaultPipelineDescriptor(context))) {}

  explicit ComputePipelineT(
      const Context& context,
      std::optional<ComputePipelineDescriptor> compute_desc)
      : ComputePipelineT(CreatePipelineFuture(context, compute_desc)) {}

  explicit ComputePipelineT(PipelineFuture<ComputePipelineDescriptor> future)
      : pipeline_future_(std::move(future)) {}

  std::shared_ptr<Pipeline<ComputePipelineDescriptor>> WaitAndGet() {
    if (did_wait_) {
      return pipeline_;
    }
    did_wait_ = true;
    if (pipeline_future_.IsValid()) {
      pipeline_ = pipeline_future_.Get();
    }
    return pipeline_;
  }

 private:
  PipelineFuture<ComputePipelineDescriptor> pipeline_future_;
  std::shared_ptr<Pipeline<ComputePipelineDescriptor>> pipeline_;
  bool did_wait_ = false;

  ComputePipelineT(const ComputePipelineT&) = delete;

  ComputePipelineT& operator=(const ComputePipelineT&) = delete;
};

}  // namespace impeller

#endif  // FLUTTER_IMPELLER_RENDERER_PIPELINE_H_
