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

#include "impeller/renderer/backend/metal/render_pass_mtl.h"

#include "flutter/fml/closure.h"
#include "flutter/fml/logging.h"
#include "flutter/fml/make_copyable.h"
#include "fml/status.h"

#include "impeller/base/backend_cast.h"
#include "impeller/core/formats.h"
#include "impeller/core/host_buffer.h"
#include "impeller/core/shader_types.h"
#include "impeller/renderer/backend/metal/context_mtl.h"
#include "impeller/renderer/backend/metal/device_buffer_mtl.h"
#include "impeller/renderer/backend/metal/formats_mtl.h"
#include "impeller/renderer/backend/metal/pipeline_mtl.h"
#include "impeller/renderer/backend/metal/sampler_mtl.h"
#include "impeller/renderer/backend/metal/texture_mtl.h"
#include "impeller/renderer/command.h"
#include "impeller/renderer/vertex_descriptor.h"

namespace impeller {

static bool ConfigureResolveTextureAttachment(
    const Attachment& desc,
    MTLRenderPassAttachmentDescriptor* attachment) {
  bool needs_resolve =
      desc.store_action == StoreAction::kMultisampleResolve ||
      desc.store_action == StoreAction::kStoreAndMultisampleResolve;

  if (needs_resolve && !desc.resolve_texture) {
    VALIDATION_LOG << "Resolve store action specified on attachment but no "
                      "resolve texture was specified.";
    return false;
  }

  if (desc.resolve_texture && !needs_resolve) {
    VALIDATION_LOG << "A resolve texture was specified even though the store "
                      "action doesn't require it.";
    return false;
  }

  if (!desc.resolve_texture) {
    return true;
  }

  attachment.resolveTexture =
      TextureMTL::Cast(*desc.resolve_texture).GetMTLTexture();

  return true;
}

static bool ConfigureAttachment(const Attachment& desc,
                                MTLRenderPassAttachmentDescriptor* attachment) {
  if (!desc.texture) {
    return false;
  }

  attachment.texture = TextureMTL::Cast(*desc.texture).GetMTLTexture();
  attachment.loadAction = ToMTLLoadAction(desc.load_action);
  attachment.storeAction = ToMTLStoreAction(desc.store_action);

  if (!ConfigureResolveTextureAttachment(desc, attachment)) {
    return false;
  }

  return true;
}

static bool ConfigureColorAttachment(
    const ColorAttachment& desc,
    MTLRenderPassColorAttachmentDescriptor* attachment) {
  if (!ConfigureAttachment(desc, attachment)) {
    return false;
  }
  attachment.clearColor = ToMTLClearColor(desc.clear_color);
  return true;
}

static bool ConfigureDepthAttachment(
    const DepthAttachment& desc,
    MTLRenderPassDepthAttachmentDescriptor* attachment) {
  if (!ConfigureAttachment(desc, attachment)) {
    return false;
  }
  attachment.clearDepth = desc.clear_depth;
  return true;
}

static bool ConfigureStencilAttachment(
    const StencilAttachment& desc,
    MTLRenderPassStencilAttachmentDescriptor* attachment) {
  if (!ConfigureAttachment(desc, attachment)) {
    return false;
  }
  attachment.clearStencil = desc.clear_stencil;
  return true;
}

// TODO(csg): Move this to formats_mtl.h
static MTLRenderPassDescriptor* ToMTLRenderPassDescriptor(
    const RenderTarget& desc) {
  auto result = [MTLRenderPassDescriptor renderPassDescriptor];

  const auto& colors = desc.GetColorAttachments();

  for (const auto& color : colors) {
    if (!ConfigureColorAttachment(color.second,
                                  result.colorAttachments[color.first])) {
      VALIDATION_LOG << "Could not configure color attachment at index "
                     << color.first;
      return nil;
    }
  }

  const auto& depth = desc.GetDepthAttachment();

  if (depth.has_value() &&
      !ConfigureDepthAttachment(depth.value(), result.depthAttachment)) {
    VALIDATION_LOG << "Could not configure depth attachment.";
    return nil;
  }

  const auto& stencil = desc.GetStencilAttachment();

  if (stencil.has_value() &&
      !ConfigureStencilAttachment(stencil.value(), result.stencilAttachment)) {
    VALIDATION_LOG << "Could not configure stencil attachment.";
    return nil;
  }

  return result;
}

RenderPassMTL::RenderPassMTL(std::shared_ptr<const Context> context,
                             const RenderTarget& target,
                             id<MTLCommandBuffer> buffer)
    : RenderPass(std::move(context), target),
      buffer_(buffer),
      desc_(ToMTLRenderPassDescriptor(GetRenderTarget())) {
  if (!buffer_ || !desc_ || !render_target_.IsValid()) {
    return;
  }
  encoder_ = [buffer_ renderCommandEncoderWithDescriptor:desc_];

  if (!encoder_) {
    return;
  }
#ifdef IMPELLER_DEBUG
  is_metal_trace_active_ =
      [[MTLCaptureManager sharedCaptureManager] isCapturing];
#endif  // IMPELLER_DEBUG
  pass_bindings_.SetEncoder(encoder_);
  pass_bindings_.SetViewport(
      Viewport{.rect = Rect::MakeSize(GetRenderTargetSize())});
  pass_bindings_.SetScissor(IRect::MakeSize(GetRenderTargetSize()));
  is_valid_ = true;
}

RenderPassMTL::~RenderPassMTL() {
  if (!did_finish_encoding_) {
    [encoder_ endEncoding];
    did_finish_encoding_ = true;
  }
}

bool RenderPassMTL::IsValid() const {
  return is_valid_;
}

void RenderPassMTL::OnSetLabel(std::string label) {
#ifdef IMPELLER_DEBUG
  if (label.empty()) {
    return;
  }
  encoder_.label = @(std::string(label).c_str());
#endif  // IMPELLER_DEBUG
}

bool RenderPassMTL::OnEncodeCommands(const Context& context) const {
  did_finish_encoding_ = true;
  [encoder_ endEncoding];
  return true;
}

static bool Bind(PassBindingsCacheMTL& pass,
                 ShaderStage stage,
                 size_t bind_index,
                 const BufferView& view) {
  if (!view.buffer) {
    return false;
  }

  auto device_buffer = view.buffer;
  if (!device_buffer) {
    return false;
  }

  auto buffer = DeviceBufferMTL::Cast(*device_buffer).GetMTLBuffer();
  // The Metal call is a void return and we don't want to make it on nil.
  if (!buffer) {
    return false;
  }

  return pass.SetBuffer(stage, bind_index, view.range.offset, buffer);
}

static bool Bind(PassBindingsCacheMTL& pass,
                 ShaderStage stage,
                 size_t bind_index,
                 const std::unique_ptr<const Sampler>& sampler,
                 const Texture& texture) {
  if (!sampler || !texture.IsValid()) {
    return false;
  }

  if (texture.NeedsMipmapGeneration()) {
    // TODO(127697): generate mips when the GPU is available on iOS.
#if !FML_OS_IOS
    VALIDATION_LOG
        << "Texture at binding index " << bind_index
        << " has a mip count > 1, but the mipmap has not been generated.";
    return false;
#endif  // !FML_OS_IOS
  }

  return pass.SetTexture(stage, bind_index,
                         TextureMTL::Cast(texture).GetMTLTexture()) &&
         pass.SetSampler(stage, bind_index,
                         SamplerMTL::Cast(*sampler).GetMTLSamplerState());
}

// |RenderPass|
void RenderPassMTL::SetPipeline(
    const std::shared_ptr<Pipeline<PipelineDescriptor>>& pipeline) {
  const PipelineDescriptor& pipeline_desc = pipeline->GetDescriptor();
  primitive_type_ = pipeline_desc.GetPrimitiveType();
  pass_bindings_.SetRenderPipelineState(
      PipelineMTL::Cast(*pipeline).GetMTLRenderPipelineState());
  pass_bindings_.SetDepthStencilState(
      PipelineMTL::Cast(*pipeline).GetMTLDepthStencilState());

  [encoder_ setFrontFacingWinding:pipeline_desc.GetWindingOrder() ==
                                          WindingOrder::kClockwise
                                      ? MTLWindingClockwise
                                      : MTLWindingCounterClockwise];
  [encoder_ setCullMode:ToMTLCullMode(pipeline_desc.GetCullMode())];
  [encoder_ setTriangleFillMode:ToMTLTriangleFillMode(
                                    pipeline_desc.GetPolygonMode())];
  has_valid_pipeline_ = true;
}

// |RenderPass|
void RenderPassMTL::SetCommandLabel(std::string_view label) {
#ifdef IMPELLER_DEBUG
  if (is_metal_trace_active_) {
    has_label_ = true;
    std::string label_copy(label);
    [encoder_ pushDebugGroup:@(label_copy.c_str())];
  }
#endif  // IMPELLER_DEBUG
}

// |RenderPass|
void RenderPassMTL::SetStencilReference(uint32_t value) {
  [encoder_ setStencilReferenceValue:value];
}

// |RenderPass|
void RenderPassMTL::SetBaseVertex(uint64_t value) {
  base_vertex_ = value;
}

// |RenderPass|
void RenderPassMTL::SetViewport(Viewport viewport) {
  pass_bindings_.SetViewport(viewport);
}

// |RenderPass|
void RenderPassMTL::SetScissor(IRect scissor) {
  pass_bindings_.SetScissor(scissor);
}

// |RenderPass|
void RenderPassMTL::SetInstanceCount(size_t count) {
  instance_count_ = count;
}

// |RenderPass|
bool RenderPassMTL::SetVertexBuffer(VertexBuffer buffer) {
  if (buffer.index_type == IndexType::kUnknown) {
    return false;
  }

  if (!Bind(pass_bindings_, ShaderStage::kVertex,
            VertexDescriptor::kReservedVertexBufferIndex,
            buffer.vertex_buffer)) {
    return false;
  }

  vertex_count_ = buffer.vertex_count;
  if (buffer.index_type != IndexType::kNone) {
    index_type_ = ToMTLIndexType(buffer.index_type);
    index_buffer_ = std::move(buffer.index_buffer);
  }
  return true;
}

// |RenderPass|
fml::Status RenderPassMTL::Draw() {
  if (!has_valid_pipeline_) {
    return fml::Status(fml::StatusCode::kCancelled, "Invalid pipeline.");
  }

  if (!index_buffer_) {
    if (instance_count_ != 1u) {
      [encoder_ drawPrimitives:ToMTLPrimitiveType(primitive_type_)
                   vertexStart:base_vertex_
                   vertexCount:vertex_count_
                 instanceCount:instance_count_
                  baseInstance:0u];
    } else {
      [encoder_ drawPrimitives:ToMTLPrimitiveType(primitive_type_)
                   vertexStart:base_vertex_
                   vertexCount:vertex_count_];
    }
  } else {
    id<MTLBuffer> mtl_index_buffer =
        DeviceBufferMTL::Cast(*index_buffer_.buffer).GetMTLBuffer();
    if (instance_count_ != 1u) {
      [encoder_ drawIndexedPrimitives:ToMTLPrimitiveType(primitive_type_)
                           indexCount:vertex_count_
                            indexType:index_type_
                          indexBuffer:mtl_index_buffer
                    indexBufferOffset:index_buffer_.range.offset
                        instanceCount:instance_count_
                           baseVertex:base_vertex_
                         baseInstance:0u];
    } else {
      [encoder_ drawIndexedPrimitives:ToMTLPrimitiveType(primitive_type_)
                           indexCount:vertex_count_
                            indexType:index_type_
                          indexBuffer:mtl_index_buffer
                    indexBufferOffset:index_buffer_.range.offset];
    }
  }

#ifdef IMPELLER_DEBUG
  if (has_label_) {
    [encoder_ popDebugGroup];
  }
#endif  // IMPELLER_DEBUG

  vertex_count_ = 0u;
  base_vertex_ = 0u;
  instance_count_ = 1u;
  index_buffer_ = {};
  has_valid_pipeline_ = false;
  has_label_ = false;

  return fml::Status();
}

// |RenderPass|
bool RenderPassMTL::BindResource(ShaderStage stage,
                                 DescriptorType type,
                                 const ShaderUniformSlot& slot,
                                 const ShaderMetadata& metadata,
                                 BufferView view) {
  return Bind(pass_bindings_, stage, slot.ext_res_0, view);
}

// |RenderPass|
bool RenderPassMTL::BindResource(
    ShaderStage stage,
    DescriptorType type,
    const ShaderUniformSlot& slot,
    const std::shared_ptr<const ShaderMetadata>& metadata,
    BufferView view) {
  return Bind(pass_bindings_, stage, slot.ext_res_0, view);
}

// |RenderPass|
bool RenderPassMTL::BindResource(
    ShaderStage stage,
    DescriptorType type,
    const SampledImageSlot& slot,
    const ShaderMetadata& metadata,
    std::shared_ptr<const Texture> texture,
    const std::unique_ptr<const Sampler>& sampler) {
  return Bind(pass_bindings_, stage, slot.texture_index, sampler, *texture);
}

}  // namespace impeller
