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

#include "src/gpu/graphite/QueueManager.h"

#include "include/gpu/GpuTypes.h"
#include "include/gpu/graphite/BackendTexture.h"
#include "include/gpu/graphite/Recording.h"
#include "include/private/SkAssert.h"
#include "include/private/SkLog.h"
#include "src/core/SkTraceEvent.h"
#include "src/gpu/GpuTypesPriv.h"
#include "src/gpu/RefCntedCallback.h"
#include "src/gpu/graphite/Buffer.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/CommandBuffer.h"
#include "src/gpu/graphite/ContextPriv.h"
#include "src/gpu/graphite/GpuWorkSubmission.h"
#include "src/gpu/graphite/RecordingPriv.h"
#include "src/gpu/graphite/Surface_Graphite.h"
#include "src/gpu/graphite/Texture.h"
#include "src/gpu/graphite/UploadBufferManager.h"
#include "src/gpu/graphite/task/Task.h"
#include "src/gpu/graphite/task/TaskList.h"

namespace skgpu::graphite {

// This constant determines how many OutstandingSubmissions are allocated together as a block in
// the deque. As such it needs to balance allocating too much memory vs. incurring
// allocation/deallocation thrashing. It should roughly correspond to the max number of outstanding
// submissions we expect to see.
static constexpr int kDefaultOutstandingAllocCnt = 8;

QueueManager::QueueManager(const SharedContext* sharedContext)
        : fSharedContext(sharedContext)
        , fOutstandingSubmissions(sizeof(OutstandingSubmission), kDefaultOutstandingAllocCnt) {
}

QueueManager::~QueueManager() {
    for (int i = 0; i < fFinishedProcs.size(); ++i) {
        fFinishedProcs[i]->setFailureResult();
    }
    fFinishedProcs.clear();

    if (fSharedContext->caps()->allowCpuSync()) {
        this->checkForFinishedWork(SyncToCpu::kYes);
    } else if (!fOutstandingSubmissions.empty()) {
        SK_ABORT("When ContextOptions::fNeverYieldToWebGPU is specified all GPU work "
                 "must be finished before destroying Context.");
    }
}

std::vector<std::unique_ptr<CommandBuffer>>*
QueueManager::getAvailableCommandBufferList(Protected isProtected) {
    return isProtected == Protected::kNo ? &fAvailableCommandBuffers
                                         : &fAvailableProtectedCommandBuffers;
}


bool QueueManager::setupCommandBuffer(ResourceProvider* resourceProvider, Protected isProtected) {
    std::unique_ptr<CommandBuffer>& commandBuffer
            = isProtected == Protected::kNo ? fCurrentCommandBuffer
                                            : fCurrentProtectedCommandBuffer;
    if (!commandBuffer) {
        std::vector<std::unique_ptr<CommandBuffer>>* bufferList =
                this->getAvailableCommandBufferList(isProtected);
        if (!bufferList->empty()) {
            commandBuffer = std::move(bufferList->back());
            bufferList->pop_back();
            if (!commandBuffer->setNewCommandBufferResources()) {
                commandBuffer.reset();
            }
        }
    }
    if (!commandBuffer) {
        commandBuffer = this->getNewCommandBuffer(resourceProvider, isProtected);
    }
    if (!commandBuffer) {
        return false;
    }

    return true;
}

CommandBuffer* QueueManager::getCurrentCommandBuffer(Protected isProtected) {
    return isProtected == Protected::kNo ? fCurrentCommandBuffer.get()
                                         : fCurrentProtectedCommandBuffer.get();
}

Protected QueueManager::getDefaultProtectedness() {
    return skgpu::Protected(fSharedContext->caps()->protectedSupport());
}

InsertStatus QueueManager::addRecording(const InsertRecordingInfo& info, Context* context) {
    TRACE_EVENT0_ALWAYS("skia.gpu", "AddRecording");

    // Configure the callback before validation so that failures are propagated to the finish
    // procs that were registered on `info` as well.
    GpuStatsFlags activeStatsFlags = GpuStatsFlags::kNone;
    sk_sp<RefCntedCallback> callback;
    if (info.fFinishedWithStatsProc) {
        activeStatsFlags = info.fGpuStatsFlags;
        if (activeStatsFlags != GpuStatsFlags::kNone) {
            GpuStatsFlags unsupportedStatsFlags = activeStatsFlags & ~context->supportedGpuStats();
            if (unsupportedStatsFlags != GpuStatsFlags::kNone) {
                activeStatsFlags &= ~unsupportedStatsFlags;
                SKIA_LOG_W("Requested GpuStats reporting (0x%x) but not supported by Context.",
                            static_cast<uint32_t>(unsupportedStatsFlags));
            }
        }
        callback = RefCntedCallback::Make(info.fFinishedWithStatsProc, info.fFinishedContext);
    } else if (info.fFinishedProc) {
        callback = RefCntedCallback::Make(info.fFinishedProc, info.fFinishedContext);
    }

#define RETURN_FAIL_IF(failureCase, status, fmt, ...)                   \
    if (failureCase) {                                                  \
        if (callback) { callback->setFailureResult(); }                 \
        if (info.fRecording) {                                          \
            info.fRecording->priv().setFailureResultForFinishedProcs(); \
            info.fRecording->priv().deinstantiateVolatileLazyProxies(); \
        }                                                               \
        SKIA_LOG_E(fmt, ##__VA_ARGS__);                                 \
        return status;                                                  \
    } do {} while(false)
#define SIMULATE_FAIL(status) \
    RETURN_FAIL_IF(info.fSimulatedStatus == status, status, "Simulating '" #status "' failure")

    RETURN_FAIL_IF(!info.fRecording,
                   InsertStatus::kInvalidRecording,
                   "Cannot insert null Recording");

    // Recordings from a Recorder that requires ordered recordings will have a valid recorder ID.
    // Recordings that don't have any required order are assigned SK_InvalidID.
    uint32_t recorderID = info.fRecording->priv().recorderID();
    if (recorderID != SK_InvalidGenID) {
        uint32_t* recordingID = fLastAddedRecordingIDs.find(recorderID);
        RETURN_FAIL_IF(recordingID && info.fRecording->priv().uniqueID() != *recordingID + 1,
                       InsertStatus::kOutOfOrderRecording,
                       "Recordings are expected to be replayed in order");

        // Note the new Recording ID.
        fLastAddedRecordingIDs.set(recorderID, info.fRecording->priv().uniqueID());
    }

    RETURN_FAIL_IF(info.fTargetSurface && !asSB(info.fTargetSurface)->isGraphiteBacked(),
                   InsertStatus::kInvalidRecording,
                    "Target surface passed into addRecording call is not Graphite-backed");

    SIMULATE_FAIL(InsertStatus::kInvalidRecording);

    auto resourceProvider = context->priv().resourceProvider();
    // Technically no commands have been added yet, but if this fails, things are in a bad state
    // so signal the unrecoverable status.
    RETURN_FAIL_IF(!this->setupCommandBuffer(resourceProvider, fSharedContext->isProtected()),
                   InsertStatus::kAddCommandsFailed,
                   "CommandBuffer creation failed");

    // This must happen before instantiating the lazy proxies, because the target for draws in this
    // recording may itself be a lazy proxy whose instantiation must be handled specially here.
    // We must also make sure the lazy proxies are instantiated successfully before we make any
    // modifications to the current command buffer, so we can't just do all this work in
    // Recording::addCommands below.
    TextureProxy* deferredTargetProxy = info.fRecording->priv().deferredTargetProxy();
    AutoDeinstantiateTextureProxy autoDeinstantiateTargetProxy(deferredTargetProxy);
    const Texture* replayTarget = nullptr;
    if (deferredTargetProxy) {
        RETURN_FAIL_IF(!info.fTargetSurface,
                       InsertStatus::kPromiseImageInstantiationFailed,
                       "No surface provided to instantiate deferred replay target");

        replayTarget = info.fRecording->priv().setupDeferredTarget(
                resourceProvider,
                static_cast<Surface*>(info.fTargetSurface),
                info.fTargetTranslation,
                info.fTargetClip);

        RETURN_FAIL_IF(!replayTarget,
                        InsertStatus::kPromiseImageInstantiationFailed,
                        "Failed to set up deferred replay target");
    }

    RETURN_FAIL_IF(info.fRecording->priv().hasNonVolatileLazyProxies() &&
                   !info.fRecording->priv().instantiateNonVolatileLazyProxies(resourceProvider),
                   InsertStatus::kPromiseImageInstantiationFailed,
                   "Non-volatile PromiseImage instantiation has failed");

    RETURN_FAIL_IF(info.fRecording->priv().hasVolatileLazyProxies() &&
                   !info.fRecording->priv().instantiateVolatileLazyProxies(resourceProvider),
                   InsertStatus::kPromiseImageInstantiationFailed,
                   "Volitile PromiseImage instantiation has failed");

    SIMULATE_FAIL(InsertStatus::kPromiseImageInstantiationFailed);

    CommandBuffer* activeCmdBuffer =
            this->getCurrentCommandBuffer(fSharedContext->isProtected());
    if (activeStatsFlags != GpuStatsFlags::kNone) {
        // TODO(b/567979421): See how supported protected command buffer stats querying is, possibly
        // could move this to an unprotected command buffer before/after.
        if (!activeCmdBuffer->startStatsQuery(activeStatsFlags)) {
            activeStatsFlags = GpuStatsFlags::kNone;
        }
    }
    activeCmdBuffer->addWaitSemaphores(info.fNumWaitSemaphores, info.fWaitSemaphores);
    if (!info.fRecording->priv().addCommands(context,
                                             activeCmdBuffer,
                                             replayTarget,
                                             info.fTargetTranslation,
                                             info.fTargetClip)) {
        // If the commands failed, iterate over all the used pipelines to see if their async
        // compilation was the reason for failure. Clients that manage pipeline disk caches may
        // want to handle the failure differently than when any other GPU command failed.
        // We will only report the 1st pipeline creation's failure message.
        std::string failureMsg;
        const bool validPipelines = info.fRecording->priv().taskList()->visitPipelines(
                [&failureMsg](const GraphicsPipeline* pipeline) {
                    if (auto failure = pipeline->didAsyncCompilationFail()) {
                        failureMsg = *failure;
                        return false;
                    }
                    return true;
                });

        // We are already definitely going to fail, it's just a matter of which status to return
        RETURN_FAIL_IF(validPipelines,
                       InsertStatus::kAddCommandsFailed,
                       "Adding Recording commands to the CommandBuffer has failed");
        RETURN_FAIL_IF(
                true,
                InsertStatus(InsertStatus::kAsyncShaderCompilesFailed, std::move(failureMsg)),
                "Async pipeline compiles failed, unable to add Recording commands");
    }

    SIMULATE_FAIL(InsertStatus::kAddCommandsFailed);
    SIMULATE_FAIL(InsertStatus::kAsyncShaderCompilesFailed);

    // When inserting recordings we will only have one active command buffer dependent on the
    // context's protectedness.
    // TODO(b/560237587): Support multiple command buffers at once.
    if (activeCmdBuffer) {
        activeCmdBuffer->addSignalSemaphores(info.fNumSignalSemaphores, info.fSignalSemaphores);
        if (info.fTargetTextureState) {
            activeCmdBuffer->prepareSurfaceForStateUpdate(info.fTargetSurface,
                                                          info.fTargetTextureState);
        }
        if (activeStatsFlags != GpuStatsFlags::kNone) {
            activeCmdBuffer->endStatsQuery(activeStatsFlags);
        }
    }

    info.fRecording->priv().moveFinishedProcsTo(fFinishedProcs);
    if (callback) {
        fFinishedProcs.push_back(std::move(callback));
    }

    info.fRecording->priv().deinstantiateVolatileLazyProxies();

    // If we got here, the simulated status should be kSuccess or it means we missed returning the
    // simulated error earlier.
    SkASSERT(info.fSimulatedStatus == InsertStatus::kSuccess);
    return InsertStatus(InsertStatus::kSuccess,
                        activeCmdBuffer->numPendingCommands(),
                        activeCmdBuffer->numPendingPasses());
}

bool QueueManager::addTask(Task* task,
                           Context* context,
                           Protected isProtected) {
    SkASSERT(task);
    if (!task) {
        SKIA_LOG_E("No valid Task passed into addTask call");
        return false;
    }

    if (!this->setupCommandBuffer(context->priv().resourceProvider(), isProtected)) {
        SKIA_LOG_E("CommandBuffer creation failed");
        return false;
    }

    CommandBuffer* activeCmdBuffer = this->getCurrentCommandBuffer(isProtected);
    if (task->addCommands(context, activeCmdBuffer, {}) == Task::Status::kFail) {
        SKIA_LOG_E("Adding Task commands to the CommandBuffer has failed");
        return false;
    }

    return true;
}

bool QueueManager::addFinishInfo(const InsertFinishInfo& info,
                                 ResourceProvider* resourceProvider,
                                 SkSpan<const sk_sp<Buffer>> buffersToAsyncMap) {
    sk_sp<RefCntedCallback> callback;
    if (info.fFinishedProc) {
        callback = RefCntedCallback::Make(info.fFinishedProc, info.fFinishedContext);
    }

    if (!this->setupCommandBuffer(resourceProvider, this->getDefaultProtectedness())) {
        if (callback) {
            callback->setFailureResult();
        }
        SKIA_LOG_E("CommandBuffer creation failed");
        return false;
    }

    CommandBuffer* activeCmdBuffer = this->getCurrentCommandBuffer(this->getDefaultProtectedness());
    if (callback) {
        fFinishedProcs.push_back(std::move(callback));
    }
    activeCmdBuffer->addBuffersToAsyncMapOnSubmit(buffersToAsyncMap);

    return true;
}

bool QueueManager::prepareBackendTextureForStateUpdate(const BackendTexture& texture,
                                                       const skgpu::MutableTextureState* newState,
                                                       ResourceProvider* resourceProvider) {
    if (!this->setupCommandBuffer(resourceProvider, texture.info().isProtected())) {
        SKIA_LOG_E("CommandBuffer creation failed");
        return false;
    }

    CommandBuffer* activeCmdBuffer = this->getCurrentCommandBuffer(texture.info().isProtected());
    activeCmdBuffer->prepareBackendTextureForStateUpdate(texture, newState);
    return true;
}

bool QueueManager::submitToGpu(const SubmitInfo& submitInfo) {
    TRACE_EVENT0_ALWAYS("skia.gpu", "SubmitToGPU");

    sk_sp<RefCntedCallback> callback;
    if (submitInfo.fFinishedProc) {
        callback = RefCntedCallback::Make(submitInfo.fFinishedProc, submitInfo.fFinishedContext);
    }

    if (!fCurrentCommandBuffer && !fCurrentProtectedCommandBuffer) {
        // If a finish proc was provided, attach it to the most recent outstanding submission,
        // or let it fire immediately if the GPU is idle (when callback goes out of scope).
        if (callback) {
            if (!fOutstandingSubmissions.empty()) {
                OutstandingSubmission* back =
                        (OutstandingSubmission*)fOutstandingSubmissions.back();
                (*back)->addFinishedProc(std::move(callback));
            }
            return true;
        }
        // We warn because this probably representative of a bad client state, where they don't
        // need to submit but didn't notice, but technically the submit itself is fine (no-op),
        // so we return true.
        SKIA_LOG_D("Submit called with no active command buffer!");
        return true;
    }

    if (callback) {
        fFinishedProcs.push_back(std::move(callback));
    }

    auto submission = this->onSubmitToGpu(submitInfo);
    if (!submission) {
        for (int i = 0; i < fFinishedProcs.size(); ++i) {
            fFinishedProcs[i]->setFailureResult();
        }
        fFinishedProcs.clear();
        return false;
    }

    submission->addFinishedProcs(std::move(fFinishedProcs));

    new (fOutstandingSubmissions.push_back()) OutstandingSubmission(std::move(submission));
    return true;
}

bool QueueManager::hasUnfinishedGpuWork() { return !fOutstandingSubmissions.empty(); }

bool QueueManager::hasPendingGPUWork() const {
    // Only check if fCurrentCommandBuffer/fCurrentProtectedCommandBuffer is non-null.
    // If there is no command in the command buffer i.e. fCurrentCommandBuffer->hasWork() is false,
    // it's still considered valid. Because clients can insert a recording without any command just
    // to track the finish proc.
    return fCurrentCommandBuffer != nullptr || fCurrentProtectedCommandBuffer != nullptr;
}

void QueueManager::checkForFinishedWork(SyncToCpu sync) {
    TRACE_EVENT1("skia.gpu", TRACE_FUNC, "sync", sync == SyncToCpu::kYes);

    if (sync == SyncToCpu::kYes) {
        SkASSERT(fSharedContext->caps()->allowCpuSync());
        // wait for the last submission to finish
        OutstandingSubmission* back = (OutstandingSubmission*)fOutstandingSubmissions.back();
        if (back) {
            (*back)->waitUntilFinished(fSharedContext);
        }
    }

    // Iterate over all the outstanding submissions to see if any have finished. The work
    // submissions are in order from oldest to newest, so we start at the front to check if they
    // have finished. If so we pop it off and move onto the next.
    // Repeat till we find a submission that has not finished yet (and all others afterwards are
    // also guaranteed to not have finished).
    OutstandingSubmission* front = (OutstandingSubmission*)fOutstandingSubmissions.front();
    while (front && (*front)->isFinished(fSharedContext)) {
        // Make sure we remove before deleting as deletion might try to kick off another submit
        // (though hopefully *not* in Graphite).
        fOutstandingSubmissions.pop_front();

        // Since we used placement new we are responsible for calling the destructor manually.
        front->~OutstandingSubmission();
        front = (OutstandingSubmission*)fOutstandingSubmissions.front();
    }
    SkASSERT(sync == SyncToCpu::kNo || fOutstandingSubmissions.empty());
}

void QueueManager::returnCommandBuffer(std::unique_ptr<CommandBuffer> commandBuffer) {
    std::vector<std::unique_ptr<CommandBuffer>>* bufferList =
            this->getAvailableCommandBufferList(commandBuffer->isProtected());
    bufferList->push_back(std::move(commandBuffer));
}

void QueueManager::addUploadBufferManagerRefs(UploadBufferManager* uploadManager,
                                              ResourceProvider* resourceProvider) {
    this->setupCommandBuffer(resourceProvider, Protected::kNo);
    SkASSERT(fCurrentCommandBuffer);
    uploadManager->transferToCommandBuffer(fCurrentCommandBuffer.get());
}

} // namespace skgpu::graphite
