// 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()),
            sizeof(float) * uniform_buffer.size(), 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
