// Copyright 2018 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 "garnet/public/lib/escher/escher.h"
#include "garnet/public/lib/escher/hmd/pose_buffer.h"
#include "garnet/public/lib/escher/hmd/pose_buffer_latching_shader.h"
#include "garnet/public/lib/escher/renderer/frame.h"
#include "garnet/public/lib/escher/resources/resource_recycler.h"
#include "garnet/public/lib/escher/scene/camera.h"
#include "garnet/public/lib/escher/test/gtest_vulkan.h"
#include "garnet/public/lib/escher/util/epsilon_compare.h"
#include "garnet/public/lib/escher/vk/buffer.h"
#include "garnet/public/lib/escher/vk/gpu_allocator.h"
#include "gtest/gtest.h"

#include <glm/gtc/type_ptr.hpp>

namespace escher {
namespace test {

// Returns true iff |a| and |b| are the same within optional |epsilon|.
bool ComparePose(escher::hmd::Pose* p0, escher::hmd::Pose* p1,
                 float epsilon = 0.0) {
  bool compare = true;

  EXPECT_TRUE(CompareFloat(p0->a, p1->a, epsilon));
  compare = compare && CompareFloat(p0->a, p1->a, epsilon);

  EXPECT_TRUE(CompareFloat(p0->b, p1->b, epsilon));
  compare = compare && CompareFloat(p0->b, p1->b, epsilon);

  EXPECT_TRUE(CompareFloat(p0->c, p1->c, epsilon));
  compare = compare && CompareFloat(p0->c, p1->c, epsilon);

  EXPECT_TRUE(CompareFloat(p0->d, p1->d, epsilon));
  compare = compare && CompareFloat(p0->d, p1->d, epsilon);

  EXPECT_TRUE(CompareFloat(p0->x, p1->x, epsilon));
  compare = compare && CompareFloat(p0->x, p1->x, epsilon);

  EXPECT_TRUE(CompareFloat(p0->y, p1->y, epsilon));
  compare = compare && CompareFloat(p0->y, p1->y, epsilon);

  EXPECT_TRUE(CompareFloat(p0->z, p1->z, epsilon));
  compare = compare && CompareFloat(p0->z, p1->z, epsilon);

  return true;
}

glm::mat4 MatrixFromPose(const hmd::Pose& pose) {
  return glm::toMat4(glm::quat(pose.d, pose.a, pose.b, pose.c)) *
         glm::translate(mat4(), glm::vec3(pose.x, pose.y, pose.z));
}

VK_TEST(PoseBuffer, ComputeShaderLatching) {
  // Initialize Vulkan.
  escher::VulkanInstance::Params instance_params(
      {{"VK_LAYER_LUNARG_standard_validation"},
       {VK_EXT_DEBUG_REPORT_EXTENSION_NAME},
       false});

  auto vulkan_instance =
      escher::VulkanInstance::New(std::move(instance_params));
  auto vulkan_device = escher::VulkanDeviceQueues::New(vulkan_instance, {});

  auto escher = std::make_unique<escher::Escher>(vulkan_device);
  escher::FramePtr frame = escher->NewFrame("PoseBufferLatchingTest", 0);

  uint32_t num_entries = 8;
  uint64_t base_time = 42L;              // Choose an arbitrary, non-zero time.
  uint64_t time_interval = 1024 * 1024;  // 1 ms

  vk::DeviceSize pose_buffer_size = num_entries * sizeof(escher::hmd::Pose);
  vk::MemoryPropertyFlags memory_property_flags =
      vk::MemoryPropertyFlagBits::eHostVisible |
      vk::MemoryPropertyFlagBits::eHostCoherent;
  vk::BufferUsageFlags buffer_usage_flags =
      vk::BufferUsageFlagBits::eUniformBuffer |
      vk::BufferUsageFlagBits::eStorageBuffer;

  // Create the shader.
  hmd::PoseBuffer pose_buffer(escher->gpu_allocator()->AllocateBuffer(
                                  escher->resource_recycler(), pose_buffer_size,
                                  buffer_usage_flags, memory_property_flags),
                              num_entries, base_time, time_interval);

  hmd::PoseBufferLatchingShader test_shader(escher->GetWeakPtr());

  // Fill the pose buffer.
  ASSERT_NE(nullptr, pose_buffer.buffer->host_ptr());
  hmd::Pose* poses =
      reinterpret_cast<hmd::Pose*>(pose_buffer.buffer->host_ptr());
  float pi = glm::pi<float>();
  for (uint32_t i = 0; i < num_entries; i++) {
    // Change pose each interation. The goal is to have unique poses in each
    // slot of the buffer where the first pose is the identity pose.
    glm::vec3 pos = vec3(i * 3.f, i * 5.f, i * 7.f);
    vec3 euler_angles(2 * pi / num_entries * i);
    glm::quat quat(euler_angles);
    new (&poses[i]) escher::hmd::Pose(quat, pos);
  }

  // Dispatch shaders.
  std::vector<BufferPtr> output_buffers;
  std::vector<Camera> cameras;
  // Dispatch a few extra to test modulo rollover.
  uint32_t num_dispatches = num_entries * 2;
  for (uint32_t i = 0; i < num_dispatches; i++) {
    // Identity Camera.
    Camera camera(glm::mat4(1), glm::mat4(1));
    // Use identity camera for first iteration only, change for all others.
    if (i != 0) {
      camera = Camera(
          glm::rotate(glm::mat4(), 2 * pi / num_dispatches * i, vec3(1, 1, 1)),
          glm::perspective(45.0f, 1.0f, 0.1f, 100.0f));
    }

    uint64_t latch_time = base_time + (time_interval * (0.5 + i));
    output_buffers.push_back(
        test_shader.LatchPose(frame, camera, pose_buffer, latch_time, true));
    cameras.push_back(camera);
  }

  // Dispatch the shader once to test the stereo flow.
  // This is kept simple as most of the functionality is tested above.
  // Identity Camera.
  Camera left_camera(glm::mat4(1), glm::mat4(2));
  Camera right_camera(glm::mat4(1), glm::mat4(3));
  BufferPtr stereo_output_buffer = test_shader.LatchStereoPose(
      frame, left_camera, right_camera, pose_buffer, base_time, true);

  // Execute shaders.
  frame->EndFrame(nullptr, []() {});
  auto result = escher->vk_device().waitIdle();
  ASSERT_EQ(vk::Result::eSuccess, result);

  // Verify results.
  for (uint32_t i = 0; i < num_dispatches; i++) {
    auto output_buffer = output_buffers[i];
    ASSERT_NE(nullptr, output_buffer->host_ptr());
    uint32_t index = i % num_entries;
    auto pose_in = &poses[index];
    auto pose_out = reinterpret_cast<hmd::Pose*>(output_buffer->host_ptr());
    EXPECT_TRUE(ComparePose(pose_in, pose_out, 0.0));
    glm::mat4 vp_matrix_in = cameras[i].projection() *
                             MatrixFromPose(*pose_in) * cameras[i].transform();
    glm::mat4 vp_matrix_out = glm::make_mat4(reinterpret_cast<float*>(
        output_buffer->host_ptr() + sizeof(hmd::Pose)));
    EXPECT_TRUE(CompareMatrix(vp_matrix_in, vp_matrix_out, 0.00001));

    // Pose zero uses all identity params so VP result should be identity.
    if (i == 0) {
      EXPECT_TRUE(CompareMatrix(mat4(), vp_matrix_out, 0.0));
    }
  }

  // Stereo flow:
  glm::mat4 left_vp_matrix_in = left_camera.projection() *
                                MatrixFromPose(poses[0]) *
                                left_camera.transform();
  glm::mat4 left_vp_matrix_out = glm::make_mat4(reinterpret_cast<float*>(
      stereo_output_buffer->host_ptr() + sizeof(hmd::Pose)));
  EXPECT_TRUE(CompareMatrix(left_vp_matrix_in, left_vp_matrix_out, 0.00001));

  glm::mat4 right_vp_matrix_in = right_camera.projection() *
                                 MatrixFromPose(poses[0]) *
                                 right_camera.transform();
  glm::mat4 right_vp_matrix_out = glm::make_mat4(
      reinterpret_cast<float*>(stereo_output_buffer->host_ptr() +
                               sizeof(hmd::Pose) + 16 * sizeof(float)));
  EXPECT_TRUE(CompareMatrix(right_vp_matrix_in, right_vp_matrix_out, 0.00001));

  escher->Cleanup();
}

}  // namespace test
}  // namespace escher
