//
// Copyright 2021 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// CLEventVk.cpp: Implements the class methods for CLEventVk.

#include "libANGLE/renderer/vulkan/CLEventVk.h"
#include "libANGLE/renderer/vulkan/CLCommandQueueVk.h"

#include "libANGLE/cl_utils.h"

namespace rx
{

CLEventVk::CLEventVk(const cl::Event &event,
                     const cl::ExecutionStatus initialStatus,
                     const QueueSerial eventSerial)
    : CLEventImpl(event),
      mStatus(cl::ToCLenum(initialStatus)),
      mProfilingTimestamps(ProfilingTimestamps{}),
      mQueueSerial(eventSerial)
{
    ANGLE_CL_IMPL_TRY(setTimestamp(*mStatus));
}

CLEventVk::~CLEventVk() {}

angle::Result CLEventVk::onEventCreate()
{
    ASSERT(!isUserEvent());
    ASSERT(mQueueSerial.valid());

    if (cl::FromCLenum<cl::ExecutionStatus>(*mStatus) == cl::ExecutionStatus::Complete)
    {
        // Submission finished at this point, just set event to complete
        ANGLE_TRY(setStatusAndExecuteCallback(CL_COMPLETE));
    }
    else
    {
        getFrontendObject().getCommandQueue()->getImpl<CLCommandQueueVk>().addEventReference(*this);
        if (getFrontendObject().getCommandQueue()->getProperties().intersects(
                CL_QUEUE_PROFILING_ENABLE))
        {
            // Block for profiling so that we get timestamps per-command
            ANGLE_TRY(getFrontendObject().getCommandQueue()->getImpl<CLCommandQueueVk>().finish());
        }
    }
    return angle::Result::Continue;
}

angle::Result CLEventVk::getCommandExecutionStatus(cl_int &executionStatus)
{
    executionStatus = *mStatus;
    return angle::Result::Continue;
}

angle::Result CLEventVk::setUserEventStatus(cl_int executionStatus)
{
    ASSERT(isUserEvent());

    // Not much to do here other than storing the user supplied state.
    // Error checking and single call enforcement is responsibility of the front end.
    ANGLE_TRY(setStatusAndExecuteCallback(executionStatus));

    // User event set and callback(s) finished - notify those waiting
    mUserEventCondition.notify_all();

    return angle::Result::Continue;
}

angle::Result CLEventVk::setCallback(cl::Event &event, cl_int commandExecCallbackType)
{
    ASSERT(commandExecCallbackType >= CL_COMPLETE);
    ASSERT(commandExecCallbackType < CL_QUEUED);

    // Not much to do, acknowledge the presence of callback and returns
    mHaveCallbacks->at(commandExecCallbackType) = true;

    return angle::Result::Continue;
}

angle::Result CLEventVk::getProfilingInfo(cl::ProfilingInfo name,
                                          size_t valueSize,
                                          void *value,
                                          size_t *valueSizeRet)
{
    cl_ulong valueUlong   = 0;
    size_t copySize       = 0;
    const void *copyValue = nullptr;

    auto profilingTimestamps = mProfilingTimestamps.synchronize();

    switch (name)
    {
        case cl::ProfilingInfo::CommandQueued:
            valueUlong = profilingTimestamps->commandQueuedTS;
            break;
        case cl::ProfilingInfo::CommandSubmit:
            valueUlong = profilingTimestamps->commandSubmitTS;
            break;
        case cl::ProfilingInfo::CommandStart:
            valueUlong = profilingTimestamps->commandStartTS;
            break;
        case cl::ProfilingInfo::CommandEnd:
            valueUlong = profilingTimestamps->commandEndTS;
            break;
        case cl::ProfilingInfo::CommandComplete:
            valueUlong = profilingTimestamps->commandCompleteTS;
            break;
        default:
            UNREACHABLE();
    }
    copyValue = &valueUlong;
    copySize  = sizeof(valueUlong);

    if ((value != nullptr) && (copyValue != nullptr))
    {
        memcpy(value, copyValue, std::min(valueSize, copySize));
    }

    if (valueSizeRet != nullptr)
    {
        *valueSizeRet = copySize;
    }

    return angle::Result::Continue;
}

angle::Result CLEventVk::waitForUserEventStatus()
{
    ASSERT(isUserEvent());

    cl_int status = CL_QUEUED;
    std::unique_lock<std::mutex> ul(mUserEventMutex);
    ANGLE_TRY(getCommandExecutionStatus(status));
    if (status > CL_COMPLETE)
    {
        // User is responsible for setting the user-event object, we need to wait for that event
        // (We dont care what the outcome is, just need to wait until that event triggers)
        INFO() << "Waiting for user-event (" << &mEvent
               << ") to be set! (aka clSetUserEventStatus)";
        mUserEventCondition.wait(ul);
    }

    return angle::Result::Continue;
}

angle::Result CLEventVk::setStatusAndExecuteCallback(cl_int status)
{
    auto statusHandle        = mStatus.synchronize();
    auto haveCallbacksHandle = mHaveCallbacks.synchronize();

    // we might skip states in some cases i.e. move from QUEUED to COMPLETE, so
    // make sure we are setting time stamps for all transitions
    ASSERT(*statusHandle >= status);
    while (*statusHandle > status)
    {
        (*statusHandle)--;
        ANGLE_TRY(setTimestamp(*statusHandle));
        if (*statusHandle >= CL_COMPLETE && *statusHandle < CL_QUEUED &&
            haveCallbacksHandle->at(*statusHandle))
        {
            getFrontendObject().callback(*statusHandle);
            haveCallbacksHandle->at(*statusHandle) = false;
        }
    }

    return angle::Result::Continue;
}

angle::Result CLEventVk::setTimestamp(cl_int status)
{
    if (!isUserEvent() &&
        mEvent.getCommandQueue()->getProperties().intersects(CL_QUEUE_PROFILING_ENABLE))
    {
        // TODO(aannestrand) Just get current CPU timestamp for now, look into Vulkan GPU device
        // timestamp query instead and later make CPU timestamp a fallback if GPU timestamp cannot
        // be queried http://anglebug.com/357902514
        cl_ulong cpuTS =
            std::chrono::time_point_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now())
                .time_since_epoch()
                .count();

        auto profilingTimestamps = mProfilingTimestamps.synchronize();

        switch (status)
        {
            case CL_QUEUED:
                profilingTimestamps->commandQueuedTS = cpuTS;
                break;
            case CL_SUBMITTED:
                profilingTimestamps->commandSubmitTS = cpuTS;
                break;
            case CL_RUNNING:
                profilingTimestamps->commandStartTS = cpuTS;
                break;
            case CL_COMPLETE:
                profilingTimestamps->commandEndTS = cpuTS;

                // Returns a value equivalent to passing CL_PROFILING_COMMAND_END if the device
                // associated with event does not support device-side enqueue.
                // https://registry.khronos.org/OpenCL/specs/3.0-unified/html/OpenCL_API.html#_device_side_enqueue
                profilingTimestamps->commandCompleteTS = cpuTS;
                break;
            default:
                UNREACHABLE();
        }
    }

    return angle::Result::Continue;
}

}  // namespace rx
