// Copyright 2017 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/graphics/tests/vkreadback/vkreadback.h"

#include <condition_variable>
#include <cstdint>
#include <mutex>
#include <queue>
#include <thread>
#include <vector>

#include <gtest/gtest.h>

#include "src/graphics/tests/common/utils.h"

#include <vulkan/vulkan.hpp>

namespace {

constexpr int64_t ms_to_ns(int64_t ms) { return ms * 1000000ll; }

}  // namespace

TEST(Vulkan, Readback) {
  VkReadbackTest test;
  ASSERT_TRUE(test.Initialize(VK_API_VERSION_1_1));
  ASSERT_TRUE(test.Exec());
  ASSERT_TRUE(test.Readback());
}

TEST(Vulkan, ReadbackMultiple) {
  std::vector<std::unique_ptr<VkReadbackTest>> readback_tests;
  constexpr int kReadbackCount = 75;
  for (int i = 0; i < kReadbackCount; i++) {
    auto readback_test = std::make_unique<VkReadbackTest>();
    ASSERT_TRUE(readback_test->Initialize(VK_API_VERSION_1_1));
    ASSERT_TRUE(readback_test->Exec());
    readback_tests.push_back(std::move(readback_test));
  }
  for (auto& readback_test : readback_tests) {
    ASSERT_TRUE(readback_test->Readback());
  }
}

TEST(Vulkan, ReadbackLoopWithFenceWaitOnSeparateThread) {
  VkReadbackTest readback_test;
  ASSERT_TRUE(readback_test.Initialize(VK_API_VERSION_1_1));

  std::mutex mutex;
  std::condition_variable cond_var;
  std::queue<vk::UniqueFence> fences;

  constexpr int kFenceCount = 500;
  const vk::Device device = readback_test.vulkan_device();

  std::thread fence_waiting_thread([&mutex, &cond_var, &fences, &device] {
    for (int i = 0; i < kFenceCount; i++) {
      vk::UniqueFence fence;

      while (!fence) {
        std::unique_lock<std::mutex> lock(mutex);
        if (fences.empty()) {
          cond_var.wait(lock);
          continue;
        }
        fence = std::move(fences.front());
        fences.pop();
      }

      EXPECT_EQ(vk::Result::eSuccess,
                device.waitForFences(*fence, /* waitAll= */ true, ms_to_ns(1000)));
    }
  });

  const vk::FenceCreateInfo fence_info{};
  for (int i = 0; i < kFenceCount; i++) {
    auto [fence_result, fence] = device.createFenceUnique(fence_info);
    ASSERT_EQ(fence_result, vk::Result::eSuccess);
    EXPECT_TRUE(readback_test.Submit(
        {.include_start_transition = (i == 0), .include_end_barrier = (i == kFenceCount - 1)},
        fence.get()));

    {
      std::unique_lock<std::mutex> lock(mutex);
      fences.push(std::move(fence));
    }
    cond_var.notify_one();
    EXPECT_TRUE(readback_test.Wait());
  }

  fence_waiting_thread.join();

  EXPECT_TRUE(readback_test.Readback());
}

TEST(Vulkan, ReadbackLoopWithFenceWait) {
  VkReadbackTest test;
  ASSERT_TRUE(test.Initialize(VK_API_VERSION_1_1));

  const vk::Device device = test.vulkan_device();

  auto [fence_result, fence] = device.createFenceUnique(vk::FenceCreateInfo{});
  ASSERT_EQ(fence_result, vk::Result::eSuccess);

  constexpr int kIterationCount = 500;
  for (int i = 0; i < kIterationCount; i++) {
    EXPECT_TRUE(
        test.Submit({.include_start_transition = (i == 0), .include_end_barrier = true}, *fence));

    EXPECT_EQ(vk::Result::eSuccess,
              device.waitForFences(*fence, /* waitAll= */ true, ms_to_ns(1000)));

    device.resetFences(*fence);

    EXPECT_TRUE(test.Readback());
  }
}

TEST(Vulkan, ReadbackLoopWithTimelineWait) {
  VkReadbackTest readback_test;

  ASSERT_TRUE(readback_test.Initialize(VK_API_VERSION_1_2));
  auto timeline_semaphore_support = readback_test.timeline_semaphore_support();

  if (timeline_semaphore_support == VulkanExtensionSupportState::kNotSupported) {
    fprintf(stderr, "Timeline semaphore feature not supported. Test skipped.\n");
    GTEST_SKIP();
  }

  const vk::Device device = readback_test.vulkan_device();

  vk::UniqueSemaphore semaphore{};
  {
    // Initialize a timeline semaphore with initial value of 0.
    vk::StructureChain<vk::SemaphoreCreateInfo, vk::SemaphoreTypeCreateInfo> create_info;
    create_info.get<vk::SemaphoreTypeCreateInfo>().semaphoreType = vk::SemaphoreType::eTimeline;
    auto create_semaphore_result = device.createSemaphoreUnique(create_info.get());
    ASSERT_EQ(vk::Result::eSuccess, create_semaphore_result.result);
    semaphore = std::move(create_semaphore_result.value);
  }

  constexpr int kSemaphoreUpdateCount = 500;
  for (int i = 0; i < kSemaphoreUpdateCount; i++) {
    const uint64_t timeline_value = 1 + i;

    {
      // Every time we submit commands to VkQueue, the value of the timeline
      // semaphore will increment by 1.
      EXPECT_TRUE(
          readback_test.Submit({.include_start_transition = (i == 0), .include_end_barrier = true},
                               *semaphore, timeline_value));
    }

    {
      // Wait until the timeline semaphore value is updated.
      vk::SemaphoreWaitInfo wait_info(vk::SemaphoreWaitFlags{}, *semaphore, timeline_value);

      // We'll use Vulkan 1.2 core API only if it is supported; otherwise we
      // use Vulkan 1.1 with extension instead. Ditto for below.
      vk::Result wait_result = vk::Result::eErrorInitializationFailed;
      switch (timeline_semaphore_support) {
        case VulkanExtensionSupportState::kSupportedInCore:
          wait_result = device.waitSemaphores(wait_info, ms_to_ns(1000));
          break;
        case VulkanExtensionSupportState::kSupportedAsExtensionOnly:
          wait_result =
              device.waitSemaphoresKHR(wait_info, ms_to_ns(1000), readback_test.vulkan_loader());
          break;
        case VulkanExtensionSupportState::kNotSupported:
          __builtin_unreachable();
          break;
      }
      EXPECT_EQ(vk::Result::eSuccess, wait_result);
    }

    {
      // Verify that the timeline semaphore counter has been updated.
      vk::ResultValue<uint64_t> counter_result(vk::Result::eErrorInitializationFailed, 0u);
      switch (timeline_semaphore_support) {
        case VulkanExtensionSupportState::kSupportedInCore:
          counter_result = device.getSemaphoreCounterValue(*semaphore);
          break;
        case VulkanExtensionSupportState::kSupportedAsExtensionOnly:
          counter_result =
              device.getSemaphoreCounterValueKHR(*semaphore, readback_test.vulkan_loader());
          break;
        case VulkanExtensionSupportState::kNotSupported:
          __builtin_unreachable();
          break;
      }
      EXPECT_EQ(counter_result.result, vk::Result::eSuccess);
      EXPECT_EQ(counter_result.value, timeline_value);
    }

    EXPECT_TRUE(readback_test.Readback());
  }
}
