// 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/entity/contents/runtime_effect_contents.h"

#include <future>
#include <memory>

#include "flutter/fml/logging.h"
#include "flutter/fml/make_copyable.h"
#include "impeller/base/validation.h"
#include "impeller/core/formats.h"
#include "impeller/core/runtime_types.h"
#include "impeller/core/shader_types.h"
#include "impeller/entity/contents/clip_contents.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/runtime_effect.vert.h"
#include "impeller/renderer/pipeline_library.h"
#include "impeller/renderer/render_pass.h"
#include "impeller/renderer/shader_function.h"

namespace impeller {

void RuntimeEffectContents::SetRuntimeStage(
    std::shared_ptr<RuntimeStage> runtime_stage) {
  runtime_stage_ = std::move(runtime_stage);
}

void RuntimeEffectContents::SetUniformData(
    std::shared_ptr<std::vector<uint8_t>> uniform_data) {
  uniform_data_ = std::move(uniform_data);
}

void RuntimeEffectContents::SetTextureInputs(
    std::vector<TextureInput> texture_inputs) {
  texture_inputs_ = std::move(texture_inputs);
}

bool RuntimeEffectContents::CanInheritOpacity(const Entity& entity) const {
  return false;
}

static ShaderType GetShaderType(RuntimeUniformType type) {
  switch (type) {
    case kSampledImage:
      return ShaderType::kSampledImage;
    case kFloat:
      return ShaderType::kFloat;
    case kStruct:
      return ShaderType::kStruct;
  }
}

static std::shared_ptr<ShaderMetadata> MakeShaderMetadata(
    const RuntimeUniformDescription& uniform) {
  auto metadata = std::make_shared<ShaderMetadata>();
  metadata->name = uniform.name;
  metadata->members.emplace_back(ShaderStructMemberMetadata{
      .type = GetShaderType(uniform.type),
      .size = uniform.GetSize(),
      .byte_length = uniform.bit_width / 8,
  });

  return metadata;
}

bool RuntimeEffectContents::Render(const ContentContext& renderer,
                                   const Entity& entity,
                                   RenderPass& pass) const {
  auto context = renderer.GetContext();
  auto library = context->GetShaderLibrary();

  //--------------------------------------------------------------------------
  /// Get or register shader.
  ///

  // TODO(113719): Register the shader function earlier.

  std::shared_ptr<const ShaderFunction> function = library->GetFunction(
      runtime_stage_->GetEntrypoint(), ShaderStage::kFragment);

  if (function && runtime_stage_->IsDirty()) {
    context->GetPipelineLibrary()->RemovePipelinesWithEntryPoint(function);
    library->UnregisterFunction(runtime_stage_->GetEntrypoint(),
                                ShaderStage::kFragment);

    function = nullptr;
  }

  if (!function) {
    std::promise<bool> promise;
    auto future = promise.get_future();

    library->RegisterFunction(
        runtime_stage_->GetEntrypoint(),
        ToShaderStage(runtime_stage_->GetShaderStage()),
        runtime_stage_->GetCodeMapping(),
        fml::MakeCopyable([promise = std::move(promise)](bool result) mutable {
          promise.set_value(result);
        }));

    if (!future.get()) {
      VALIDATION_LOG << "Failed to build runtime effect (entry point: "
                     << runtime_stage_->GetEntrypoint() << ")";
      return false;
    }

    function = library->GetFunction(runtime_stage_->GetEntrypoint(),
                                    ShaderStage::kFragment);
    if (!function) {
      VALIDATION_LOG
          << "Failed to fetch runtime effect function immediately after "
             "registering it (entry point: "
          << runtime_stage_->GetEntrypoint() << ")";
      return false;
    }

    runtime_stage_->SetClean();
  }

  //--------------------------------------------------------------------------
  /// Resolve geometry.
  ///

  auto geometry_result =
      GetGeometry()->GetPositionBuffer(renderer, entity, pass);

  //--------------------------------------------------------------------------
  /// Set up the command. Defer setting up the pipeline until the descriptor set
  /// layouts are known from the uniforms.
  ///

  const auto& caps = context->GetCapabilities();
  const auto color_attachment_format = caps->GetDefaultColorFormat();
  const auto stencil_attachment_format = caps->GetDefaultStencilFormat();

  using VS = RuntimeEffectVertexShader;

  pass.SetCommandLabel("RuntimeEffectContents");
  pass.SetStencilReference(entity.GetClipDepth());
  pass.SetVertexBuffer(std::move(geometry_result.vertex_buffer));

  //--------------------------------------------------------------------------
  /// Vertex stage uniforms.
  ///

  VS::FrameInfo frame_info;
  frame_info.mvp = geometry_result.transform;
  VS::BindFrameInfo(pass,
                    renderer.GetTransientsBuffer().EmplaceUniform(frame_info));

  //--------------------------------------------------------------------------
  /// Fragment stage uniforms.
  ///

  size_t minimum_sampler_index = 100000000;
  size_t buffer_index = 0;
  size_t buffer_offset = 0;

  std::vector<DescriptorSetLayout> descriptor_set_layouts;

  for (const auto& uniform : runtime_stage_->GetUniforms()) {
    std::shared_ptr<ShaderMetadata> metadata = MakeShaderMetadata(uniform);

    switch (uniform.type) {
      case kSampledImage: {
        // Sampler uniforms are ordered in the IPLR according to their
        // declaration and the uniform location reflects the correct offset to
        // be mapped to - except that it may include all proceeding float
        // uniforms. For example, a float sampler that comes after 4 float
        // uniforms may have a location of 4. To convert to the actual offset we
        // need to find the largest location assigned to a float uniform and
        // then subtract this from all uniform locations. This is more or less
        // the same operation we previously performed in the shader compiler.
        minimum_sampler_index =
            std::min(minimum_sampler_index, uniform.location);
        break;
      }
      case kFloat: {
        FML_DCHECK(renderer.GetContext()->GetBackendType() !=
                   Context::BackendType::kVulkan)
            << "Uniform " << uniform.name
            << " had unexpected type kFloat for Vulkan backend.";
        size_t alignment =
            std::max(uniform.bit_width / 8, DefaultUniformAlignment());
        auto buffer_view = renderer.GetTransientsBuffer().Emplace(
            uniform_data_->data() + buffer_offset, uniform.GetSize(),
            alignment);

        ShaderUniformSlot uniform_slot;
        uniform_slot.name = uniform.name.c_str();
        uniform_slot.ext_res_0 = uniform.location;
        pass.BindResource(ShaderStage::kFragment, uniform_slot, metadata,
                          buffer_view);
        buffer_index++;
        buffer_offset += uniform.GetSize();
        break;
      }
      case kStruct: {
        FML_DCHECK(renderer.GetContext()->GetBackendType() ==
                   Context::BackendType::kVulkan);
        descriptor_set_layouts.emplace_back(DescriptorSetLayout{
            static_cast<uint32_t>(uniform.location),
            DescriptorType::kUniformBuffer,
            ShaderStage::kFragment,
        });
        ShaderUniformSlot uniform_slot;
        uniform_slot.name = uniform.name.c_str();
        uniform_slot.binding = uniform.location;

        std::vector<float> uniform_buffer;
        uniform_buffer.reserve(uniform.struct_layout.size());
        size_t uniform_byte_index = 0u;
        for (const auto& byte_type : uniform.struct_layout) {
          if (byte_type == 0) {
            uniform_buffer.push_back(0.f);
          } else if (byte_type == 1) {
            uniform_buffer.push_back(reinterpret_cast<float*>(
                uniform_data_->data())[uniform_byte_index++]);
          } else {
            FML_UNREACHABLE();
          }
        }

        size_t alignment = std::max(sizeof(float) * uniform_buffer.size(),
                                    DefaultUniformAlignment());

        auto buffer_view = renderer.GetTransientsBuffer().Emplace(
            reinterpret_cast<const void*>(uniform_buffer.data()), alignment,
            alignment);
        pass.BindResource(ShaderStage::kFragment, uniform_slot,
                          ShaderMetadata{}, buffer_view);
      }
    }
  }

  size_t sampler_index = 0;
  for (const auto& uniform : runtime_stage_->GetUniforms()) {
    std::shared_ptr<ShaderMetadata> metadata = MakeShaderMetadata(uniform);

    switch (uniform.type) {
      case kSampledImage: {
        FML_DCHECK(sampler_index < texture_inputs_.size());
        auto& input = texture_inputs_[sampler_index];

        auto sampler =
            context->GetSamplerLibrary()->GetSampler(input.sampler_descriptor);

        SampledImageSlot image_slot;
        image_slot.name = uniform.name.c_str();

        uint32_t sampler_binding_location = 0u;
        if (!descriptor_set_layouts.empty()) {
          sampler_binding_location = descriptor_set_layouts.back().binding + 1;
        }

        descriptor_set_layouts.emplace_back(DescriptorSetLayout{
            sampler_binding_location,
            DescriptorType::kSampledImage,
            ShaderStage::kFragment,
        });

        image_slot.binding = sampler_binding_location;
        image_slot.texture_index = uniform.location - minimum_sampler_index;
        pass.BindResource(ShaderStage::kFragment, image_slot, *metadata,
                          input.texture, sampler);

        sampler_index++;
        break;
      }
      default:
        continue;
    }
  }

  /// Now that the descriptor set layouts are known, get the pipeline.

  auto options = OptionsFromPassAndEntity(pass, entity);
  if (geometry_result.prevent_overdraw) {
    options.stencil_compare = CompareFunction::kEqual;
    options.stencil_operation = StencilOperation::kIncrementClamp;
  }
  options.primitive_type = geometry_result.type;

  auto create_callback =
      [&]() -> std::shared_ptr<Pipeline<PipelineDescriptor>> {
    PipelineDescriptor desc;
    desc.SetLabel("Runtime Stage");
    desc.AddStageEntrypoint(
        library->GetFunction(VS::kEntrypointName, ShaderStage::kVertex));
    desc.AddStageEntrypoint(library->GetFunction(
        runtime_stage_->GetEntrypoint(), ShaderStage::kFragment));
    auto vertex_descriptor = std::make_shared<VertexDescriptor>();
    vertex_descriptor->SetStageInputs(VS::kAllShaderStageInputs,
                                      VS::kInterleavedBufferLayout);
    vertex_descriptor->RegisterDescriptorSetLayouts(VS::kDescriptorSetLayouts);
    vertex_descriptor->RegisterDescriptorSetLayouts(
        descriptor_set_layouts.data(), descriptor_set_layouts.size());
    desc.SetVertexDescriptor(std::move(vertex_descriptor));
    desc.SetColorAttachmentDescriptor(
        0u, {.format = color_attachment_format, .blending_enabled = true});

    StencilAttachmentDescriptor stencil0;
    stencil0.stencil_compare = CompareFunction::kEqual;
    desc.SetStencilAttachmentDescriptors(stencil0);
    desc.SetStencilPixelFormat(stencil_attachment_format);

    options.ApplyToPipelineDescriptor(desc);
    auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
    if (!pipeline) {
      VALIDATION_LOG << "Failed to get or create runtime effect pipeline.";
      return nullptr;
    }

    return pipeline;
  };

  pass.SetPipeline(renderer.GetCachedRuntimeEffectPipeline(
      runtime_stage_->GetEntrypoint(), options, create_callback));

  if (!pass.Draw().ok()) {
    return false;
  }

  if (geometry_result.prevent_overdraw) {
    auto restore = ClipRestoreContents();
    restore.SetRestoreCoverage(GetCoverage(entity));
    return restore.Render(renderer, entity, pass);
  }
  return true;
}

}  // namespace impeller
