/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "VulkanManager.h"

#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GrBackendSemaphore.h>
#include <GrBackendSurface.h>
#include <GrDirectContext.h>
#include <GrTypes.h>
#include <android/sync.h>
#include <ui/FatVector.h>
#include <vk/GrVkExtensions.h>
#include <vk/GrVkTypes.h>

#include <cstring>

#include <gui/TraceUtils.h>
#include "Properties.h"
#include "RenderThread.h"
#include "pipeline/skia/ShaderCache.h"
#include "renderstate/RenderState.h"

namespace android {
namespace uirenderer {
namespace renderthread {

static void free_features_extensions_structs(const VkPhysicalDeviceFeatures2& features) {
    // All Vulkan structs that could be part of the features chain will start with the
    // structure type followed by the pNext pointer. We cast to the CommonVulkanHeader
    // so we can get access to the pNext for the next struct.
    struct CommonVulkanHeader {
        VkStructureType sType;
        void* pNext;
    };

    void* pNext = features.pNext;
    while (pNext) {
        void* current = pNext;
        pNext = static_cast<CommonVulkanHeader*>(current)->pNext;
        free(current);
    }
}

GrVkGetProc VulkanManager::sSkiaGetProp = [](const char* proc_name, VkInstance instance,
                                             VkDevice device) {
    if (device != VK_NULL_HANDLE) {
        if (strcmp("vkQueueSubmit", proc_name) == 0) {
            return (PFN_vkVoidFunction)VulkanManager::interceptedVkQueueSubmit;
        } else if (strcmp("vkQueueWaitIdle", proc_name) == 0) {
            return (PFN_vkVoidFunction)VulkanManager::interceptedVkQueueWaitIdle;
        }
        return vkGetDeviceProcAddr(device, proc_name);
    }
    return vkGetInstanceProcAddr(instance, proc_name);
};

#define GET_PROC(F) m##F = (PFN_vk##F)vkGetInstanceProcAddr(VK_NULL_HANDLE, "vk" #F)
#define GET_INST_PROC(F) m##F = (PFN_vk##F)vkGetInstanceProcAddr(mInstance, "vk" #F)
#define GET_DEV_PROC(F) m##F = (PFN_vk##F)vkGetDeviceProcAddr(mDevice, "vk" #F)

sp<VulkanManager> VulkanManager::getInstance() {
    // cache a weakptr to the context to enable a second thread to share the same vulkan state
    static wp<VulkanManager> sWeakInstance = nullptr;
    static std::mutex sLock;

    std::lock_guard _lock{sLock};
    sp<VulkanManager> vulkanManager = sWeakInstance.promote();
    if (!vulkanManager.get()) {
        vulkanManager = new VulkanManager();
        sWeakInstance = vulkanManager;
    }

    return vulkanManager;
}

VulkanManager::~VulkanManager() {
    if (mDevice != VK_NULL_HANDLE) {
        mDeviceWaitIdle(mDevice);
        mDestroyDevice(mDevice, nullptr);
    }

    if (mInstance != VK_NULL_HANDLE) {
        mDestroyInstance(mInstance, nullptr);
    }

    mGraphicsQueue = VK_NULL_HANDLE;
    mDevice = VK_NULL_HANDLE;
    mPhysicalDevice = VK_NULL_HANDLE;
    mInstance = VK_NULL_HANDLE;
    mInstanceExtensionsOwner.clear();
    mInstanceExtensions.clear();
    mDeviceExtensionsOwner.clear();
    mDeviceExtensions.clear();
    free_features_extensions_structs(mPhysicalDeviceFeatures2);
    mPhysicalDeviceFeatures2 = {};
}

void VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFeatures2& features) {
    VkResult err;

    constexpr VkApplicationInfo app_info = {
            VK_STRUCTURE_TYPE_APPLICATION_INFO,  // sType
            nullptr,                             // pNext
            "android framework",                 // pApplicationName
            0,                                   // applicationVersion
            "android framework",                 // pEngineName
            0,                                   // engineVerison
            mAPIVersion,                         // apiVersion
    };

    {
        GET_PROC(EnumerateInstanceExtensionProperties);

        uint32_t extensionCount = 0;
        err = mEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
        LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err);
        mInstanceExtensionsOwner.resize(extensionCount);
        err = mEnumerateInstanceExtensionProperties(nullptr, &extensionCount,
                                                    mInstanceExtensionsOwner.data());
        LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err);
        bool hasKHRSurfaceExtension = false;
        bool hasKHRAndroidSurfaceExtension = false;
        for (const VkExtensionProperties& extension : mInstanceExtensionsOwner) {
            mInstanceExtensions.push_back(extension.extensionName);
            if (!strcmp(extension.extensionName, VK_KHR_SURFACE_EXTENSION_NAME)) {
                hasKHRSurfaceExtension = true;
            }
            if (!strcmp(extension.extensionName, VK_KHR_ANDROID_SURFACE_EXTENSION_NAME)) {
                hasKHRAndroidSurfaceExtension = true;
            }
        }
        LOG_ALWAYS_FATAL_IF(!hasKHRSurfaceExtension || !hasKHRAndroidSurfaceExtension);
    }

    const VkInstanceCreateInfo instance_create = {
            VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,  // sType
            nullptr,                                 // pNext
            0,                                       // flags
            &app_info,                               // pApplicationInfo
            0,                                       // enabledLayerNameCount
            nullptr,                                 // ppEnabledLayerNames
            (uint32_t)mInstanceExtensions.size(),    // enabledExtensionNameCount
            mInstanceExtensions.data(),              // ppEnabledExtensionNames
    };

    GET_PROC(CreateInstance);
    err = mCreateInstance(&instance_create, nullptr, &mInstance);
    LOG_ALWAYS_FATAL_IF(err < 0);

    GET_INST_PROC(CreateDevice);
    GET_INST_PROC(DestroyInstance);
    GET_INST_PROC(EnumerateDeviceExtensionProperties);
    GET_INST_PROC(EnumeratePhysicalDevices);
    GET_INST_PROC(GetPhysicalDeviceFeatures2);
    GET_INST_PROC(GetPhysicalDeviceImageFormatProperties2);
    GET_INST_PROC(GetPhysicalDeviceProperties);
    GET_INST_PROC(GetPhysicalDeviceQueueFamilyProperties);

    uint32_t gpuCount;
    LOG_ALWAYS_FATAL_IF(mEnumeratePhysicalDevices(mInstance, &gpuCount, nullptr));
    LOG_ALWAYS_FATAL_IF(!gpuCount);
    // Just returning the first physical device instead of getting the whole array. Since there
    // should only be one device on android.
    gpuCount = 1;
    err = mEnumeratePhysicalDevices(mInstance, &gpuCount, &mPhysicalDevice);
    // VK_INCOMPLETE is returned when the count we provide is less than the total device count.
    LOG_ALWAYS_FATAL_IF(err && VK_INCOMPLETE != err);

    VkPhysicalDeviceProperties physDeviceProperties;
    mGetPhysicalDeviceProperties(mPhysicalDevice, &physDeviceProperties);
    LOG_ALWAYS_FATAL_IF(physDeviceProperties.apiVersion < VK_MAKE_VERSION(1, 1, 0));
    mDriverVersion = physDeviceProperties.driverVersion;

    // query to get the initial queue props size
    uint32_t queueCount;
    mGetPhysicalDeviceQueueFamilyProperties(mPhysicalDevice, &queueCount, nullptr);
    LOG_ALWAYS_FATAL_IF(!queueCount);

    // now get the actual queue props
    std::unique_ptr<VkQueueFamilyProperties[]> queueProps(new VkQueueFamilyProperties[queueCount]);
    mGetPhysicalDeviceQueueFamilyProperties(mPhysicalDevice, &queueCount, queueProps.get());

    // iterate to find the graphics queue
    mGraphicsQueueIndex = queueCount;
    for (uint32_t i = 0; i < queueCount; i++) {
        if (queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
            mGraphicsQueueIndex = i;
            break;
        }
    }
    LOG_ALWAYS_FATAL_IF(mGraphicsQueueIndex == queueCount);

    {
        uint32_t extensionCount = 0;
        err = mEnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr, &extensionCount,
                                                  nullptr);
        LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err);
        mDeviceExtensionsOwner.resize(extensionCount);
        err = mEnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr, &extensionCount,
                                                  mDeviceExtensionsOwner.data());
        LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err);
        bool hasKHRSwapchainExtension = false;
        for (const VkExtensionProperties& extension : mDeviceExtensionsOwner) {
            mDeviceExtensions.push_back(extension.extensionName);
            if (!strcmp(extension.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
                hasKHRSwapchainExtension = true;
            }
        }
        LOG_ALWAYS_FATAL_IF(!hasKHRSwapchainExtension);
    }

    grExtensions.init(sSkiaGetProp, mInstance, mPhysicalDevice, mInstanceExtensions.size(),
                      mInstanceExtensions.data(), mDeviceExtensions.size(),
                      mDeviceExtensions.data());

    LOG_ALWAYS_FATAL_IF(!grExtensions.hasExtension(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, 1));

    memset(&features, 0, sizeof(VkPhysicalDeviceFeatures2));
    features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
    features.pNext = nullptr;

    // Setup all extension feature structs we may want to use.
    void** tailPNext = &features.pNext;

    if (grExtensions.hasExtension(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME, 2)) {
        VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT* blend;
        blend = (VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT*)malloc(
                sizeof(VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT));
        LOG_ALWAYS_FATAL_IF(!blend);
        blend->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT;
        blend->pNext = nullptr;
        *tailPNext = blend;
        tailPNext = &blend->pNext;
    }

    VkPhysicalDeviceSamplerYcbcrConversionFeatures* ycbcrFeature;
    ycbcrFeature = (VkPhysicalDeviceSamplerYcbcrConversionFeatures*)malloc(
            sizeof(VkPhysicalDeviceSamplerYcbcrConversionFeatures));
    LOG_ALWAYS_FATAL_IF(!ycbcrFeature);
    ycbcrFeature->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES;
    ycbcrFeature->pNext = nullptr;
    *tailPNext = ycbcrFeature;
    tailPNext = &ycbcrFeature->pNext;

    // query to get the physical device features
    mGetPhysicalDeviceFeatures2(mPhysicalDevice, &features);
    // this looks like it would slow things down,
    // and we can't depend on it on all platforms
    features.features.robustBufferAccess = VK_FALSE;

    float queuePriorities[1] = {0.0};

    void* queueNextPtr = nullptr;

    VkDeviceQueueGlobalPriorityCreateInfoEXT queuePriorityCreateInfo;

    if (Properties::contextPriority != 0 &&
        grExtensions.hasExtension(VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME, 2)) {
        memset(&queuePriorityCreateInfo, 0, sizeof(VkDeviceQueueGlobalPriorityCreateInfoEXT));
        queuePriorityCreateInfo.sType =
                VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT;
        queuePriorityCreateInfo.pNext = nullptr;
        switch (Properties::contextPriority) {
            case EGL_CONTEXT_PRIORITY_LOW_IMG:
                queuePriorityCreateInfo.globalPriority = VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT;
                break;
            case EGL_CONTEXT_PRIORITY_MEDIUM_IMG:
                queuePriorityCreateInfo.globalPriority = VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT;
                break;
            case EGL_CONTEXT_PRIORITY_HIGH_IMG:
                queuePriorityCreateInfo.globalPriority = VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT;
                break;
            default:
                LOG_ALWAYS_FATAL("Unsupported context priority");
        }
        queueNextPtr = &queuePriorityCreateInfo;
    }

    const VkDeviceQueueCreateInfo queueInfo = {
            VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,  // sType
            queueNextPtr,                                // pNext
            0,                                           // VkDeviceQueueCreateFlags
            mGraphicsQueueIndex,                         // queueFamilyIndex
            1,                                           // queueCount
            queuePriorities,                             // pQueuePriorities
    };

    const VkDeviceCreateInfo deviceInfo = {
            VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,  // sType
            &features,                             // pNext
            0,                                     // VkDeviceCreateFlags
            1,                                     // queueCreateInfoCount
            &queueInfo,                            // pQueueCreateInfos
            0,                                     // layerCount
            nullptr,                               // ppEnabledLayerNames
            (uint32_t)mDeviceExtensions.size(),    // extensionCount
            mDeviceExtensions.data(),              // ppEnabledExtensionNames
            nullptr,                               // ppEnabledFeatures
    };

    LOG_ALWAYS_FATAL_IF(mCreateDevice(mPhysicalDevice, &deviceInfo, nullptr, &mDevice));

    GET_DEV_PROC(AllocateCommandBuffers);
    GET_DEV_PROC(BeginCommandBuffer);
    GET_DEV_PROC(CmdPipelineBarrier);
    GET_DEV_PROC(CreateCommandPool);
    GET_DEV_PROC(CreateFence);
    GET_DEV_PROC(CreateSemaphore);
    GET_DEV_PROC(DestroyCommandPool);
    GET_DEV_PROC(DestroyDevice);
    GET_DEV_PROC(DestroyFence);
    GET_DEV_PROC(DestroySemaphore);
    GET_DEV_PROC(DeviceWaitIdle);
    GET_DEV_PROC(EndCommandBuffer);
    GET_DEV_PROC(FreeCommandBuffers);
    GET_DEV_PROC(GetDeviceQueue);
    GET_DEV_PROC(GetSemaphoreFdKHR);
    GET_DEV_PROC(ImportSemaphoreFdKHR);
    GET_DEV_PROC(QueueSubmit);
    GET_DEV_PROC(QueueWaitIdle);
    GET_DEV_PROC(ResetCommandBuffer);
    GET_DEV_PROC(ResetFences);
    GET_DEV_PROC(WaitForFences);
    GET_DEV_PROC(FrameBoundaryANDROID);
}

void VulkanManager::initialize() {
    std::lock_guard _lock{mInitializeLock};

    if (mDevice != VK_NULL_HANDLE) {
        return;
    }

    GET_PROC(EnumerateInstanceVersion);
    uint32_t instanceVersion;
    LOG_ALWAYS_FATAL_IF(mEnumerateInstanceVersion(&instanceVersion));
    LOG_ALWAYS_FATAL_IF(instanceVersion < VK_MAKE_VERSION(1, 1, 0));

    this->setupDevice(mExtensions, mPhysicalDeviceFeatures2);

    mGetDeviceQueue(mDevice, mGraphicsQueueIndex, 0, &mGraphicsQueue);

    if (Properties::enablePartialUpdates && Properties::useBufferAge) {
        mSwapBehavior = SwapBehavior::BufferAge;
    }
}

sk_sp<GrDirectContext> VulkanManager::createContext(const GrContextOptions& options,
                                                    ContextType contextType) {

    GrVkBackendContext backendContext;
    backendContext.fInstance = mInstance;
    backendContext.fPhysicalDevice = mPhysicalDevice;
    backendContext.fDevice = mDevice;
    backendContext.fQueue = mGraphicsQueue;
    backendContext.fGraphicsQueueIndex = mGraphicsQueueIndex;
    backendContext.fMaxAPIVersion = mAPIVersion;
    backendContext.fVkExtensions = &mExtensions;
    backendContext.fDeviceFeatures2 = &mPhysicalDeviceFeatures2;
    backendContext.fGetProc = sSkiaGetProp;

    return GrDirectContext::MakeVulkan(backendContext, options);
}

VkFunctorInitParams VulkanManager::getVkFunctorInitParams() const {
    return VkFunctorInitParams{
            .instance = mInstance,
            .physical_device = mPhysicalDevice,
            .device = mDevice,
            .queue = mGraphicsQueue,
            .graphics_queue_index = mGraphicsQueueIndex,
            .api_version = mAPIVersion,
            .enabled_instance_extension_names = mInstanceExtensions.data(),
            .enabled_instance_extension_names_length =
                    static_cast<uint32_t>(mInstanceExtensions.size()),
            .enabled_device_extension_names = mDeviceExtensions.data(),
            .enabled_device_extension_names_length =
                    static_cast<uint32_t>(mDeviceExtensions.size()),
            .device_features_2 = &mPhysicalDeviceFeatures2,
    };
}

Frame VulkanManager::dequeueNextBuffer(VulkanSurface* surface) {
    VulkanSurface::NativeBufferInfo* bufferInfo = surface->dequeueNativeBuffer();

    if (bufferInfo == nullptr) {
        ALOGE("VulkanSurface::dequeueNativeBuffer called with an invalid surface!");
        return Frame(-1, -1, 0);
    }

    LOG_ALWAYS_FATAL_IF(!bufferInfo->dequeued);

    if (bufferInfo->dequeue_fence != -1) {
        struct sync_file_info* finfo = sync_file_info(bufferInfo->dequeue_fence);
        bool isSignalPending = false;
        if (finfo != NULL) {
            isSignalPending = finfo->status != 1;
            sync_file_info_free(finfo);
        }
        if (isSignalPending) {
            int fence_clone = dup(bufferInfo->dequeue_fence);
            if (fence_clone == -1) {
                ALOGE("dup(fence) failed, stalling until signalled: %s (%d)", strerror(errno),
                      errno);
                sync_wait(bufferInfo->dequeue_fence, -1 /* forever */);
            } else {
                VkSemaphoreCreateInfo semaphoreInfo;
                semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
                semaphoreInfo.pNext = nullptr;
                semaphoreInfo.flags = 0;
                VkSemaphore semaphore;
                VkResult err = mCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore);
                if (err != VK_SUCCESS) {
                    ALOGE("Failed to create import semaphore, err: %d", err);
                    close(fence_clone);
                    sync_wait(bufferInfo->dequeue_fence, -1 /* forever */);
                } else {
                    VkImportSemaphoreFdInfoKHR importInfo;
                    importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR;
                    importInfo.pNext = nullptr;
                    importInfo.semaphore = semaphore;
                    importInfo.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT;
                    importInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
                    importInfo.fd = fence_clone;

                    err = mImportSemaphoreFdKHR(mDevice, &importInfo);
                    if (err != VK_SUCCESS) {
                        ALOGE("Failed to import semaphore, err: %d", err);
                        mDestroySemaphore(mDevice, semaphore, nullptr);
                        close(fence_clone);
                        sync_wait(bufferInfo->dequeue_fence, -1 /* forever */);
                    } else {
                        GrBackendSemaphore backendSemaphore;
                        backendSemaphore.initVulkan(semaphore);
                        // Skia will take ownership of the VkSemaphore and delete it once the wait
                        // has finished. The VkSemaphore also owns the imported fd, so it will
                        // close the fd when it is deleted.
                        bufferInfo->skSurface->wait(1, &backendSemaphore);
                        // The following flush blocks the GPU immediately instead of waiting for
                        // other drawing ops. It seems dequeue_fence is not respected otherwise.
                        // TODO: remove the flush after finding why backendSemaphore is not working.
                        bufferInfo->skSurface->flushAndSubmit();
                    }
                }
            }
        }
    }

    int bufferAge = (mSwapBehavior == SwapBehavior::Discard) ? 0 : surface->getCurrentBuffersAge();
    return Frame(surface->logicalWidth(), surface->logicalHeight(), bufferAge);
}

struct DestroySemaphoreInfo {
    PFN_vkDestroySemaphore mDestroyFunction;
    VkDevice mDevice;
    VkSemaphore mSemaphore;
    // We need to make sure we don't delete the VkSemaphore until it is done being used by both Skia
    // (including by the GPU) and inside the VulkanManager. So we always start with two refs, one
    // owned by Skia and one owned by the VulkanManager. The refs are decremented each time
    // destroy_semaphore is called with this object. Skia will call destroy_semaphore once it is
    // done with the semaphore and the GPU has finished work on the semaphore. The VulkanManager
    // calls destroy_semaphore after sending the semaphore to Skia and exporting it if need be.
    int mRefs = 2;

    DestroySemaphoreInfo(PFN_vkDestroySemaphore destroyFunction, VkDevice device,
                         VkSemaphore semaphore)
            : mDestroyFunction(destroyFunction), mDevice(device), mSemaphore(semaphore) {}
};

static void destroy_semaphore(void* context) {
    DestroySemaphoreInfo* info = reinterpret_cast<DestroySemaphoreInfo*>(context);
    --info->mRefs;
    if (!info->mRefs) {
        info->mDestroyFunction(info->mDevice, info->mSemaphore, nullptr);
        delete info;
    }
}

void VulkanManager::finishFrame(SkSurface* surface) {
    ATRACE_NAME("Vulkan finish frame");
    ALOGE_IF(mSwapSemaphore != VK_NULL_HANDLE || mDestroySemaphoreContext != nullptr,
             "finishFrame already has an outstanding semaphore");

    VkExportSemaphoreCreateInfo exportInfo;
    exportInfo.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO;
    exportInfo.pNext = nullptr;
    exportInfo.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;

    VkSemaphoreCreateInfo semaphoreInfo;
    semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
    semaphoreInfo.pNext = &exportInfo;
    semaphoreInfo.flags = 0;
    VkSemaphore semaphore;
    VkResult err = mCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore);
    ALOGE_IF(VK_SUCCESS != err, "VulkanManager::makeSwapSemaphore(): Failed to create semaphore");

    GrBackendSemaphore backendSemaphore;
    backendSemaphore.initVulkan(semaphore);

    GrFlushInfo flushInfo;
    if (err == VK_SUCCESS) {
        mDestroySemaphoreContext = new DestroySemaphoreInfo(mDestroySemaphore, mDevice, semaphore);
        flushInfo.fNumSemaphores = 1;
        flushInfo.fSignalSemaphores = &backendSemaphore;
        flushInfo.fFinishedProc = destroy_semaphore;
        flushInfo.fFinishedContext = mDestroySemaphoreContext;
    } else {
        semaphore = VK_NULL_HANDLE;
    }
    GrSemaphoresSubmitted submitted =
            surface->flush(SkSurface::BackendSurfaceAccess::kPresent, flushInfo);
    GrDirectContext* context = GrAsDirectContext(surface->recordingContext());
    ALOGE_IF(!context, "Surface is not backed by gpu");
    context->submit();
    if (semaphore != VK_NULL_HANDLE) {
        if (submitted == GrSemaphoresSubmitted::kYes) {
            mSwapSemaphore = semaphore;
            if (mFrameBoundaryANDROID) {
                // retrieve VkImage used as render target
                VkImage image = VK_NULL_HANDLE;
                GrBackendRenderTarget backendRenderTarget =
                        surface->getBackendRenderTarget(SkSurface::kFlushRead_BackendHandleAccess);
                if (backendRenderTarget.isValid()) {
                    GrVkImageInfo info;
                    if (backendRenderTarget.getVkImageInfo(&info)) {
                        image = info.fImage;
                    } else {
                        ALOGE("Frame boundary: backend is not vulkan");
                    }
                } else {
                    ALOGE("Frame boundary: invalid backend render target");
                }
                // frameBoundaryANDROID needs to know about mSwapSemaphore, but
                // it won't wait on it.
                mFrameBoundaryANDROID(mDevice, mSwapSemaphore, image);
            }
        } else {
            destroy_semaphore(mDestroySemaphoreContext);
            mDestroySemaphoreContext = nullptr;
        }
    }
    skiapipeline::ShaderCache::get().onVkFrameFlushed(context);
}

void VulkanManager::swapBuffers(VulkanSurface* surface, const SkRect& dirtyRect) {
    if (CC_UNLIKELY(Properties::waitForGpuCompletion)) {
        ATRACE_NAME("Finishing GPU work");
        mDeviceWaitIdle(mDevice);
    }

    int fenceFd = -1;
    if (mSwapSemaphore != VK_NULL_HANDLE) {
        VkSemaphoreGetFdInfoKHR getFdInfo;
        getFdInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR;
        getFdInfo.pNext = nullptr;
        getFdInfo.semaphore = mSwapSemaphore;
        getFdInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;

        VkResult err = mGetSemaphoreFdKHR(mDevice, &getFdInfo, &fenceFd);
        ALOGE_IF(VK_SUCCESS != err, "VulkanManager::swapBuffers(): Failed to get semaphore Fd");
    } else {
        ALOGE("VulkanManager::swapBuffers(): Semaphore submission failed");

        std::lock_guard<std::mutex> lock(mGraphicsQueueMutex);
        mQueueWaitIdle(mGraphicsQueue);
    }
    if (mDestroySemaphoreContext) {
        destroy_semaphore(mDestroySemaphoreContext);
    }

    surface->presentCurrentBuffer(dirtyRect, fenceFd);
    mSwapSemaphore = VK_NULL_HANDLE;
    mDestroySemaphoreContext = nullptr;
}

void VulkanManager::destroySurface(VulkanSurface* surface) {
    // Make sure all submit commands have finished before starting to destroy objects.
    if (VK_NULL_HANDLE != mGraphicsQueue) {
        std::lock_guard<std::mutex> lock(mGraphicsQueueMutex);
        mQueueWaitIdle(mGraphicsQueue);
    }
    mDeviceWaitIdle(mDevice);

    delete surface;
}

VulkanSurface* VulkanManager::createSurface(ANativeWindow* window,
                                            ColorMode colorMode,
                                            sk_sp<SkColorSpace> surfaceColorSpace,
                                            SkColorType surfaceColorType,
                                            GrDirectContext* grContext,
                                            uint32_t extraBuffers) {
    LOG_ALWAYS_FATAL_IF(!hasVkContext(), "Not initialized");
    if (!window) {
        return nullptr;
    }

    return VulkanSurface::Create(window, colorMode, surfaceColorType, surfaceColorSpace, grContext,
                                 *this, extraBuffers);
}

status_t VulkanManager::fenceWait(int fence, GrDirectContext* grContext) {
    if (!hasVkContext()) {
        ALOGE("VulkanManager::fenceWait: VkDevice not initialized");
        return INVALID_OPERATION;
    }

    // Block GPU on the fence.
    int fenceFd = ::dup(fence);
    if (fenceFd == -1) {
        ALOGE("VulkanManager::fenceWait: error dup'ing fence fd: %d", errno);
        return -errno;
    }

    VkSemaphoreCreateInfo semaphoreInfo;
    semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
    semaphoreInfo.pNext = nullptr;
    semaphoreInfo.flags = 0;
    VkSemaphore semaphore;
    VkResult err = mCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore);
    if (VK_SUCCESS != err) {
        close(fenceFd);
        ALOGE("Failed to create import semaphore, err: %d", err);
        return UNKNOWN_ERROR;
    }
    VkImportSemaphoreFdInfoKHR importInfo;
    importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR;
    importInfo.pNext = nullptr;
    importInfo.semaphore = semaphore;
    importInfo.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT;
    importInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
    importInfo.fd = fenceFd;

    err = mImportSemaphoreFdKHR(mDevice, &importInfo);
    if (VK_SUCCESS != err) {
        mDestroySemaphore(mDevice, semaphore, nullptr);
        close(fenceFd);
        ALOGE("Failed to import semaphore, err: %d", err);
        return UNKNOWN_ERROR;
    }

    GrBackendSemaphore beSemaphore;
    beSemaphore.initVulkan(semaphore);

    // Skia will take ownership of the VkSemaphore and delete it once the wait has finished. The
    // VkSemaphore also owns the imported fd, so it will close the fd when it is deleted.
    grContext->wait(1, &beSemaphore);
    grContext->flushAndSubmit();

    return OK;
}

status_t VulkanManager::createReleaseFence(int* nativeFence, GrDirectContext* grContext) {
    *nativeFence = -1;
    if (!hasVkContext()) {
        ALOGE("VulkanManager::createReleaseFence: VkDevice not initialized");
        return INVALID_OPERATION;
    }

    VkExportSemaphoreCreateInfo exportInfo;
    exportInfo.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO;
    exportInfo.pNext = nullptr;
    exportInfo.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;

    VkSemaphoreCreateInfo semaphoreInfo;
    semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
    semaphoreInfo.pNext = &exportInfo;
    semaphoreInfo.flags = 0;
    VkSemaphore semaphore;
    VkResult err = mCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore);
    if (VK_SUCCESS != err) {
        ALOGE("VulkanManager::createReleaseFence: Failed to create semaphore");
        return INVALID_OPERATION;
    }

    GrBackendSemaphore backendSemaphore;
    backendSemaphore.initVulkan(semaphore);

    DestroySemaphoreInfo* destroyInfo =
            new DestroySemaphoreInfo(mDestroySemaphore, mDevice, semaphore);
    // Even if Skia fails to submit the semaphore, it will still call the destroy_semaphore callback
    // which will remove its ref to the semaphore. The VulkanManager must still release its ref,
    // when it is done with the semaphore.
    GrFlushInfo flushInfo;
    flushInfo.fNumSemaphores = 1;
    flushInfo.fSignalSemaphores = &backendSemaphore;
    flushInfo.fFinishedProc = destroy_semaphore;
    flushInfo.fFinishedContext = destroyInfo;
    GrSemaphoresSubmitted submitted = grContext->flush(flushInfo);
    grContext->submit();

    if (submitted == GrSemaphoresSubmitted::kNo) {
        ALOGE("VulkanManager::createReleaseFence: Failed to submit semaphore");
        destroy_semaphore(destroyInfo);
        return INVALID_OPERATION;
    }

    VkSemaphoreGetFdInfoKHR getFdInfo;
    getFdInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR;
    getFdInfo.pNext = nullptr;
    getFdInfo.semaphore = semaphore;
    getFdInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;

    int fenceFd = 0;

    err = mGetSemaphoreFdKHR(mDevice, &getFdInfo, &fenceFd);
    destroy_semaphore(destroyInfo);
    if (VK_SUCCESS != err) {
        ALOGE("VulkanManager::createReleaseFence: Failed to get semaphore Fd");
        return INVALID_OPERATION;
    }
    *nativeFence = fenceFd;

    return OK;
}

} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
