/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "VkTestContext.h"

#ifdef SK_VULKAN

#include "vk/GrVkInterface.h"
#include "vk/GrVkUtil.h"
#include <vulkan/vulkan.h>

namespace {
/**
 * Implements SkGpuFenceSync for Vulkan. It creates a single command buffer with
 * USAGE_SIMULTANEOUS with no content . On every insertFence request it submits
 * the command buffer with a new fence.
 */
class VkFenceSync : public SkGpuFenceSync {
public:
    VkFenceSync(sk_sp<const GrVkInterface> vk, VkDevice device, VkQueue queue,
                uint32_t queueFamilyIndex)
            : fVk(std::move(vk))
            , fDevice(device)
            , fQueue(queue) {
        SkDEBUGCODE(fUnfinishedSyncs = 0;)
        VkCommandPoolCreateInfo createInfo;
        createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
        createInfo.pNext = nullptr;
        createInfo.flags = 0;
        createInfo.queueFamilyIndex = queueFamilyIndex;
        GR_VK_CALL_ERRCHECK(fVk, CreateCommandPool(fDevice, &createInfo, nullptr, &fCommandPool));

        VkCommandBufferAllocateInfo allocateInfo;
        allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
        allocateInfo.pNext = nullptr;
        allocateInfo.commandBufferCount = 1;
        allocateInfo.commandPool = fCommandPool;
        allocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
        GR_VK_CALL_ERRCHECK(fVk, AllocateCommandBuffers(fDevice, &allocateInfo, &fCommandBuffer));

        VkCommandBufferBeginInfo beginInfo;
        beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
        beginInfo.pNext = nullptr;
        beginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
        beginInfo.pInheritanceInfo = nullptr;
        GR_VK_CALL_ERRCHECK(fVk, BeginCommandBuffer(fCommandBuffer, &beginInfo));
        GR_VK_CALL_ERRCHECK(fVk, EndCommandBuffer(fCommandBuffer));
    }

    ~VkFenceSync() override {
        SkASSERT(!fUnfinishedSyncs);
        // If the above assertion is true then the command buffer should not be in flight.
        GR_VK_CALL(fVk, FreeCommandBuffers(fDevice, fCommandPool, 1, &fCommandBuffer));
        GR_VK_CALL(fVk, DestroyCommandPool(fDevice, fCommandPool, nullptr));
    }

    SkPlatformGpuFence SK_WARN_UNUSED_RESULT insertFence() const override {
        VkFence fence;
        VkFenceCreateInfo info;
        info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
        info.pNext = nullptr;
        info.flags = 0;
        GR_VK_CALL_ERRCHECK(fVk, CreateFence(fDevice, &info, nullptr, &fence));
        VkSubmitInfo submitInfo;
        submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
        submitInfo.pNext = nullptr;
        submitInfo.waitSemaphoreCount = 0;
        submitInfo.pWaitSemaphores = nullptr;
        submitInfo.pWaitDstStageMask = nullptr;
        submitInfo.commandBufferCount = 1;
        submitInfo.pCommandBuffers = &fCommandBuffer;
        submitInfo.signalSemaphoreCount = 0;
        submitInfo.pSignalSemaphores = nullptr;
        GR_VK_CALL_ERRCHECK(fVk, QueueSubmit(fQueue, 1, &submitInfo, fence));
        SkDEBUGCODE(++fUnfinishedSyncs;)
        return reinterpret_cast<SkPlatformGpuFence>(fence);
    }

    bool waitFence(SkPlatformGpuFence opaqueFence) const override {
        VkFence fence = reinterpret_cast<VkFence>(opaqueFence);
        static constexpr uint64_t kForever = ~((uint64_t)0);
        auto result = GR_VK_CALL(fVk, WaitForFences(fDevice, 1, &fence, true, kForever));
        return result != VK_TIMEOUT;
    }

    void deleteFence(SkPlatformGpuFence opaqueFence) const override {
        VkFence fence = reinterpret_cast<VkFence>(opaqueFence);
        GR_VK_CALL(fVk, DestroyFence(fDevice, fence, nullptr));
        SkDEBUGCODE(--fUnfinishedSyncs;)
    }

private:
    sk_sp<const GrVkInterface>  fVk;
    VkDevice                    fDevice;
    VkQueue                     fQueue;
    VkCommandPool               fCommandPool;
    VkCommandBuffer             fCommandBuffer;
    SkDEBUGCODE(mutable int     fUnfinishedSyncs;)
    typedef SkGpuFenceSync INHERITED;
};

// TODO: Implement swap buffers and finish
class VkTestContextImpl : public sk_gpu_test::VkTestContext {
public:
    static VkTestContext* Create() {
        sk_sp<const GrVkBackendContext> backendContext(GrVkBackendContext::Create());
        if (!backendContext) {
            return nullptr;
        }
        return new VkTestContextImpl(std::move(backendContext));
    }

    ~VkTestContextImpl() override { this->teardown(); }

    void testAbandon() override {}

    // There is really nothing to here since we don't own any unqueued command buffers here.
    void submit() override {}

    void finish() override {}

protected:
    void teardown() override {
        INHERITED::teardown();
        fVk.reset(nullptr);
    }

private:
    VkTestContextImpl(sk_sp<const GrVkBackendContext> backendContext)
            : VkTestContext(std::move(backendContext)) {
        fFenceSync = new VkFenceSync(sk_ref_sp(fVk->fInterface.get()), fVk->fDevice, fVk->fQueue,
                                     fVk->fGraphicsQueueIndex);
    }

    void onPlatformMakeCurrent() const override {}
    void onPlatformSwapBuffers() const override {}

    typedef sk_gpu_test::VkTestContext INHERITED;
};
}

namespace sk_gpu_test {
VkTestContext* CreatePlatformVkTestContext() { return VkTestContextImpl::Create(); }
}  // namespace sk_gpu_test

#endif
