// 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/vulkan/binding_helpers_vk.h"
#include "fml/status.h"
#include "impeller/core/shader_types.h"
#include "impeller/renderer/backend/vulkan/command_buffer_vk.h"
#include "impeller/renderer/backend/vulkan/command_encoder_vk.h"
#include "impeller/renderer/backend/vulkan/command_pool_vk.h"
#include "impeller/renderer/backend/vulkan/compute_pipeline_vk.h"
#include "impeller/renderer/backend/vulkan/context_vk.h"
#include "impeller/renderer/backend/vulkan/sampler_vk.h"
#include "impeller/renderer/backend/vulkan/texture_vk.h"
#include "impeller/renderer/command.h"
#include "impeller/renderer/compute_command.h"
#include "vulkan/vulkan_core.h"

namespace impeller {

// Warning: if any of the constant values or layouts are changed in the
// framebuffer fetch shader, then this input binding may need to be
// manually changed.
static constexpr size_t kMagicSubpassInputBinding = 64;

static bool BindImages(const Bindings& bindings,
                       Allocator& allocator,
                       const std::shared_ptr<CommandEncoderVK>& encoder,
                       vk::DescriptorSet& vk_desc_set,
                       std::vector<vk::DescriptorImageInfo>& images,
                       std::vector<vk::WriteDescriptorSet>& writes) {
  for (const TextureAndSampler& data : bindings.sampled_images) {
    auto texture = data.texture.resource;
    const auto& texture_vk = TextureVK::Cast(*texture);
    const SamplerVK& sampler = SamplerVK::Cast(*data.sampler);

    if (!encoder->Track(texture) ||
        !encoder->Track(sampler.GetSharedSampler())) {
      return false;
    }

    const SampledImageSlot& slot = data.slot;

    vk::DescriptorImageInfo image_info;
    image_info.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
    image_info.sampler = sampler.GetSampler();
    image_info.imageView = texture_vk.GetImageView();
    images.push_back(image_info);

    vk::WriteDescriptorSet write_set;
    write_set.dstSet = vk_desc_set;
    write_set.dstBinding = slot.binding;
    write_set.descriptorCount = 1u;
    write_set.descriptorType = vk::DescriptorType::eCombinedImageSampler;
    write_set.pImageInfo = &images.back();

    writes.push_back(write_set);
  }

  return true;
};

static bool BindBuffers(const Bindings& bindings,
                        Allocator& allocator,
                        const std::shared_ptr<CommandEncoderVK>& encoder,
                        vk::DescriptorSet& vk_desc_set,
                        const std::vector<DescriptorSetLayout>& desc_set,
                        std::vector<vk::DescriptorBufferInfo>& buffers,
                        std::vector<vk::WriteDescriptorSet>& writes) {
  for (const BufferAndUniformSlot& data : bindings.buffers) {
    const auto& buffer_view = data.view.resource.buffer;

    auto device_buffer = buffer_view->GetDeviceBuffer(allocator);
    if (!device_buffer) {
      VALIDATION_LOG << "Failed to get device buffer for vertex binding";
      return false;
    }

    auto buffer = DeviceBufferVK::Cast(*device_buffer).GetBuffer();
    if (!buffer) {
      return false;
    }

    if (!encoder->Track(device_buffer)) {
      return false;
    }

    uint32_t offset = data.view.resource.range.offset;

    vk::DescriptorBufferInfo buffer_info;
    buffer_info.buffer = buffer;
    buffer_info.offset = offset;
    buffer_info.range = data.view.resource.range.length;
    buffers.push_back(buffer_info);

    // TODO(jonahwilliams): remove this part by storing more data in
    // ShaderUniformSlot.
    const ShaderUniformSlot& uniform = data.slot;
    auto layout_it =
        std::find_if(desc_set.begin(), desc_set.end(),
                     [&uniform](const DescriptorSetLayout& layout) {
                       return layout.binding == uniform.binding;
                     });
    if (layout_it == desc_set.end()) {
      VALIDATION_LOG << "Failed to get descriptor set layout for binding "
                     << uniform.binding;
      return false;
    }
    auto layout = *layout_it;

    vk::WriteDescriptorSet write_set;
    write_set.dstSet = vk_desc_set;
    write_set.dstBinding = uniform.binding;
    write_set.descriptorCount = 1u;
    write_set.descriptorType = ToVKDescriptorType(layout.descriptor_type);
    write_set.pBufferInfo = &buffers.back();

    writes.push_back(write_set);
  }
  return true;
}

fml::StatusOr<std::vector<vk::DescriptorSet>> AllocateAndBindDescriptorSets(
    const ContextVK& context,
    const std::shared_ptr<CommandEncoderVK>& encoder,
    const std::vector<Command>& commands,
    const TextureVK& input_attachment) {
  if (commands.empty()) {
    return std::vector<vk::DescriptorSet>{};
  }

  // Step 1: Determine the total number of buffer and sampler descriptor
  // sets required. Collect this information along with the layout information
  // to allocate a correctly sized descriptor pool.
  size_t buffer_count = 0;
  size_t samplers_count = 0;
  size_t subpass_count = 0;
  std::vector<vk::DescriptorSetLayout> layouts;
  layouts.reserve(commands.size());

  for (const auto& command : commands) {
    buffer_count += command.vertex_bindings.buffers.size();
    buffer_count += command.fragment_bindings.buffers.size();
    samplers_count += command.fragment_bindings.sampled_images.size();
    subpass_count +=
        command.pipeline->GetDescriptor().UsesSubpassInput() ? 1 : 0;

    layouts.emplace_back(
        PipelineVK::Cast(*command.pipeline).GetDescriptorSetLayout());
  }
  auto descriptor_result = encoder->AllocateDescriptorSets(
      buffer_count, samplers_count, subpass_count, layouts);
  if (!descriptor_result.ok()) {
    return descriptor_result.status();
  }
  auto descriptor_sets = descriptor_result.value();
  if (descriptor_sets.empty()) {
    return fml::Status();
  }

  // Step 2: Update the descriptors for all image and buffer descriptors used
  // in the render pass.
  std::vector<vk::DescriptorImageInfo> images;
  std::vector<vk::DescriptorBufferInfo> buffers;
  std::vector<vk::WriteDescriptorSet> writes;
  images.reserve(samplers_count + subpass_count);
  buffers.reserve(buffer_count);
  writes.reserve(samplers_count + buffer_count + subpass_count);

  auto& allocator = *context.GetResourceAllocator();
  auto desc_index = 0u;
  for (const auto& command : commands) {
    auto desc_set = command.pipeline->GetDescriptor()
                        .GetVertexDescriptor()
                        ->GetDescriptorSetLayouts();

    if (!BindBuffers(command.vertex_bindings, allocator, encoder,
                     descriptor_sets[desc_index], desc_set, buffers, writes) ||
        !BindBuffers(command.fragment_bindings, allocator, encoder,
                     descriptor_sets[desc_index], desc_set, buffers, writes) ||
        !BindImages(command.fragment_bindings, allocator, encoder,
                    descriptor_sets[desc_index], images, writes)) {
      return fml::Status(fml::StatusCode::kUnknown,
                         "Failed to bind texture or buffer.");
    }

    if (command.pipeline->GetDescriptor().UsesSubpassInput()) {
      vk::DescriptorImageInfo image_info;
      image_info.imageLayout = vk::ImageLayout::eGeneral;
      image_info.sampler = VK_NULL_HANDLE;
      image_info.imageView = input_attachment.GetImageView();
      images.push_back(image_info);

      vk::WriteDescriptorSet write_set;
      write_set.dstSet = descriptor_sets[desc_index];
      write_set.dstBinding = kMagicSubpassInputBinding;
      write_set.descriptorCount = 1u;
      write_set.descriptorType = vk::DescriptorType::eInputAttachment;
      write_set.pImageInfo = &images.back();

      writes.push_back(write_set);
    }
    desc_index += 1;
  }

  context.GetDevice().updateDescriptorSets(writes, {});
  return descriptor_sets;
}

fml::StatusOr<std::vector<vk::DescriptorSet>> AllocateAndBindDescriptorSets(
    const ContextVK& context,
    const std::shared_ptr<CommandEncoderVK>& encoder,
    const std::vector<ComputeCommand>& commands) {
  if (commands.empty()) {
    return std::vector<vk::DescriptorSet>{};
  }
  // Step 1: Determine the total number of buffer and sampler descriptor
  // sets required. Collect this information along with the layout information
  // to allocate a correctly sized descriptor pool.
  size_t buffer_count = 0;
  size_t samplers_count = 0;
  std::vector<vk::DescriptorSetLayout> layouts;
  layouts.reserve(commands.size());

  for (const auto& command : commands) {
    buffer_count += command.bindings.buffers.size();
    samplers_count += command.bindings.sampled_images.size();

    layouts.emplace_back(
        ComputePipelineVK::Cast(*command.pipeline).GetDescriptorSetLayout());
  }
  auto descriptor_result =
      encoder->AllocateDescriptorSets(buffer_count, samplers_count, 0, layouts);
  if (!descriptor_result.ok()) {
    return descriptor_result.status();
  }
  auto descriptor_sets = descriptor_result.value();
  if (descriptor_sets.empty()) {
    return fml::Status();
  }
  // Step 2: Update the descriptors for all image and buffer descriptors used
  // in the render pass.
  std::vector<vk::DescriptorImageInfo> images;
  std::vector<vk::DescriptorBufferInfo> buffers;
  std::vector<vk::WriteDescriptorSet> writes;
  images.reserve(samplers_count);
  buffers.reserve(buffer_count);
  writes.reserve(samplers_count + buffer_count);

  auto& allocator = *context.GetResourceAllocator();
  auto desc_index = 0u;
  for (const auto& command : commands) {
    auto desc_set = command.pipeline->GetDescriptor().GetDescriptorSetLayouts();

    if (!BindBuffers(command.bindings, allocator, encoder,
                     descriptor_sets[desc_index], desc_set, buffers, writes) ||
        !BindImages(command.bindings, allocator, encoder,
                    descriptor_sets[desc_index], images, writes)) {
      return fml::Status(fml::StatusCode::kUnknown,
                         "Failed to bind texture or buffer.");
    }
    desc_index += 1;
  }

  context.GetDevice().updateDescriptorSets(writes, {});
  return descriptor_sets;
}

}  // namespace impeller
