// Copyright 2019 The Fuchsia 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 "src/ui/lib/escher/renderer/render_funcs.h"

#include "src/ui/lib/escher/escher.h"
#include "src/ui/lib/escher/impl/vulkan_utils.h"
#include "src/ui/lib/escher/util/trace_macros.h"
#include "src/ui/lib/escher/vk/render_pass.h"
#include "src/ui/lib/escher/vk/texture.h"

#include <vulkan/vulkan.hpp>

namespace escher {

// Helper for NewVertexAttributeBindings().
static RenderFuncs::VertexAttributeBinding* FillVertexAttributeBindings(
    const MeshAttributeBindingLocations& attribute_binding_locations,
    RenderFuncs::VertexAttributeBinding* binding, uint32_t binding_index,
    MeshAttributes attributes) {
  using VertexAttributeBinding = RenderFuncs::VertexAttributeBinding;

  if (attributes & MeshAttribute::kPosition2D) {
    *binding++ = VertexAttributeBinding{
        .binding_index = binding_index,
        .attribute_index = attribute_binding_locations.position_2d,
        .format = vk::Format::eR32G32Sfloat,
        .offset = GetMeshAttributeOffset(attributes, MeshAttribute::kPosition2D)};
  }
  if (attributes & MeshAttribute::kPosition3D) {
    *binding++ = VertexAttributeBinding{
        .binding_index = binding_index,
        .attribute_index = attribute_binding_locations.position_3d,
        .format = vk::Format::eR32G32B32Sfloat,
        .offset = GetMeshAttributeOffset(attributes, MeshAttribute::kPosition3D)};
  }
  if (attributes & MeshAttribute::kPositionOffset) {
    *binding++ = VertexAttributeBinding{
        .binding_index = binding_index,
        .attribute_index = attribute_binding_locations.position_offset,
        .format = vk::Format::eR32G32Sfloat,
        .offset = GetMeshAttributeOffset(attributes, MeshAttribute::kPositionOffset)};
  }
  if (attributes & MeshAttribute::kUV) {
    *binding++ =
        VertexAttributeBinding{.binding_index = binding_index,
                               .attribute_index = attribute_binding_locations.uv,
                               .format = vk::Format::eR32G32Sfloat,
                               .offset = GetMeshAttributeOffset(attributes, MeshAttribute::kUV)};
  }
  if (attributes & MeshAttribute::kPerimeterPos) {
    *binding++ = VertexAttributeBinding{
        .binding_index = binding_index,
        .attribute_index = attribute_binding_locations.perimeter_pos,
        .format = vk::Format::eR32G32Sfloat,
        .offset = GetMeshAttributeOffset(attributes, MeshAttribute::kPerimeterPos)};
  }
  if (attributes & MeshAttribute::kBlendWeight1) {
    *binding++ = VertexAttributeBinding{
        .binding_index = binding_index,
        .attribute_index = attribute_binding_locations.blend_weight1,
        .format = vk::Format::eR32Sfloat,
        .offset = GetMeshAttributeOffset(attributes, MeshAttribute::kBlendWeight1)};
  }
  return binding;
}

RenderFuncs::VertexAttributeBinding* RenderFuncs::NewVertexAttributeBindings(
    const MeshAttributeBindingLocations& attribute_binding_locations, BlockAllocator* allocator,
    const MeshSpec& mesh_spec, uint32_t total_attribute_count) {
  FX_DCHECK(total_attribute_count == mesh_spec.total_attribute_count());

  auto bindings = allocator->AllocateMany<VertexAttributeBinding>(total_attribute_count);
  {
    VertexAttributeBinding* current = bindings;
    for (uint32_t i = 0; i < VulkanLimits::kNumVertexBuffers; ++i) {
      if (mesh_spec.attribute_count(i) > 0) {
        current = FillVertexAttributeBindings(attribute_binding_locations, current, i,
                                              mesh_spec.attributes[i]);
      }
    }

    // Sanity check that we filled in the correct number of attributes.
    FX_DCHECK(current == (bindings + total_attribute_count));
  }
  return bindings;
}

void RenderFuncs::ObtainDepthAndMsaaTextures(
    Escher* escher, const FramePtr& frame, uint32_t width, uint32_t height, uint32_t sample_count,
    bool use_transient_attachment, vk::Format depth_stencil_format, vk::Format msaa_format,
    TexturePtr& depth_texture_inout, TexturePtr& msaa_texture_inout) {
  const bool realloc_textures =
      !depth_texture_inout ||
      (depth_texture_inout->image()->use_protected_memory() != frame->use_protected_memory()) ||
      (depth_texture_inout->image()->is_transient() != use_transient_attachment) ||
      width != depth_texture_inout->width() || height != depth_texture_inout->height() ||
      sample_count != depth_texture_inout->image()->info().sample_count;
  if (!realloc_textures) {
    return;
  }

  vk::ImageUsageFlags image_usage = use_transient_attachment
                                        ? vk::ImageUsageFlagBits::eTransientAttachment
                                        : vk::ImageUsageFlags();
  vk::MemoryPropertyFlags memory_properties = vk::MemoryPropertyFlagBits::eDeviceLocal;
  if (use_transient_attachment) {
    memory_properties |= vk::MemoryPropertyFlagBits::eLazilyAllocated;
  }
  if (frame->use_protected_memory()) {
    memory_properties |= vk::MemoryPropertyFlagBits::eProtected;
  }

  // Need to generate a new depth buffer.
  {
    TRACE_DURATION("gfx", "RenderFuncs::ObtainDepthAndMsaaTextures (new depth)");
    depth_texture_inout = escher->NewAttachmentTexture(
        depth_stencil_format, width, height, sample_count, vk::Filter::eLinear, image_usage,
        /*use_unnormalized_coordinates=*/false, memory_properties);
  }
  if (sample_count == 1) {
    msaa_texture_inout = nullptr;
  } else {
    TRACE_DURATION("gfx", "RenderFuncs::ObtainDepthAndMsaaTextures (new msaa)");
    msaa_texture_inout = escher->NewAttachmentTexture(
        msaa_format, width, height, sample_count, vk::Filter::eLinear, image_usage,
        /*use_unnormalized_coordinates=*/false, memory_properties);

    // Don't transition layout for transient attachment images.
    if (!use_transient_attachment) {
      frame->cmds()->ImageBarrier(msaa_texture_inout->image(), vk::ImageLayout::eUndefined,
                                  vk::ImageLayout::eColorAttachmentOptimal,
                                  vk::PipelineStageFlagBits::eAllGraphics, vk::AccessFlags(),
                                  vk::PipelineStageFlagBits::eColorAttachmentOutput,
                                  vk::AccessFlagBits::eColorAttachmentWrite);
    }
  }
}

void RenderFuncs::ObtainDepthTexture(Escher* escher, const bool use_protected_memory,
                                     const ImageInfo& info, vk::Format depth_stencil_format,
                                     TexturePtr& depth_texture) {
  // Support for other sample_counts should fairly easy to add, if necessary.
  FX_DCHECK(info.sample_count == 1);

  const bool realloc_textures =
      !depth_texture || (depth_texture->image()->use_protected_memory() != use_protected_memory) ||
      info.width != depth_texture->width() || info.height != depth_texture->height();

  // If the depth buffer does not exist, or if the depth buffer has a different
  // size than the output buffer, recreate it.
  if (realloc_textures) {
    // Need to generate a new depth buffer.
    {
      TRACE_DURATION("gfx", "RenderFuncs::ObtainDepthAndMsaaTextures (new depth)");
      depth_texture = escher->NewAttachmentTexture(
          depth_stencil_format, info.width, info.height, 1, vk::Filter::eLinear,
          vk::ImageUsageFlags(), /*use_unnormalized_coordinates=*/false,
          use_protected_memory ? vk::MemoryPropertyFlagBits::eProtected
                               : vk::MemoryPropertyFlags());
    }
  }
}
}  // namespace escher
