// 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 "gtest/gtest.h"
#include "gtest_escher.h"
#include "src/ui/lib/escher/defaults/default_shader_program_factory.h"
#include "src/ui/lib/escher/escher.h"
#include "src/ui/lib/escher/hmd/pose_buffer.h"
#include "src/ui/lib/escher/hmd/pose_buffer_latching_shader.h"
#include "src/ui/lib/escher/renderer/frame.h"
#include "src/ui/lib/escher/resources/resource_recycler.h"
#include "src/ui/lib/escher/scene/camera.h"
#include "src/ui/lib/escher/test/gtest_vulkan.h"
#include "src/ui/lib/escher/util/epsilon_compare.h"
#include "src/ui/lib/escher/vk/buffer.h"
#include "src/ui/lib/escher/vk/gpu_allocator.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));
}

using PoseBufferTest = escher::test::TestWithVkValidationLayer;

// TODO(36692): This test now causes Vulkan validation errors on AEMU.
VK_TEST_F(PoseBufferTest, ComputeShaderLatching) {
  auto escher = escher::test::EscherEnvironment::GetGlobalTestEnvironment()->GetEscher();
  escher->shader_program_factory()->filesystem()->InitializeWithRealFiles({});

  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
