// Copyright 2019 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "src/dawn/native/EncodingContext.h"

#include "src/dawn/native/CommandEncoder.h"
#include "src/dawn/native/Commands.h"
#include "src/dawn/native/Device.h"
#include "src/dawn/native/ErrorData.h"
#include "src/dawn/native/IndirectDrawValidationEncoder.h"
#include "src/dawn/native/RenderBundleEncoder.h"
#include "src/utils/assert.h"

namespace dawn::native {

EncodingContext::EncodingContext(DeviceBase* device, const ApiObjectBase* initialEncoder)
    : mDevice(device),
      mTopLevelEncoder(initialEncoder),
      mCurrentEncoder(initialEncoder),
      mStatus(Status::Open) {
    DAWN_CHECK(!initialEncoder->IsError());
}

EncodingContext::EncodingContext(DeviceBase* device, ErrorMonad::ErrorTag tag)
    : mDevice(device),
      mTopLevelEncoder(nullptr),
      mCurrentEncoder(nullptr),
      mStatus(Status::ErrorAtCreation) {}

EncodingContext::~EncodingContext() {
    Destroy();
}

void EncodingContext::Destroy() {
    mDebugGroupLabels.clear();

    if (!mWereIndirectDrawMetadataAcquired) {
        mIndirectDrawMetadata.clear();
    }
    if (!mWereCommandsAcquired) {
        CommandIterator commands = AcquireCommands();
        FreeCommands(&commands);
    }

    CloseWithStatus(Status::Destroyed);
}

CommandIterator EncodingContext::AcquireCommands() {
    DAWN_CHECK(!mWereCommandsAcquired);
    mWereCommandsAcquired = true;

    CommitCommands(std::move(mPendingCommands));

    CommandIterator commands;
    commands.AcquireCommandBlocks(std::move(mAllocators));
    return commands;
}

void EncodingContext::HandleError(std::unique_ptr<ErrorData> error) {
    // Append in reverse so that the most recently set debug group is printed first, like a
    // call stack.
    for (auto iter = mDebugGroupLabels.rbegin(); iter != mDebugGroupLabels.rend(); ++iter) {
        error->AppendDebugGroup(*iter);
    }

    bool deferErrors = mStatus != Status::Finished;
    if (mDevice->IsImmediateErrorHandlingEnabled()) {
        deferErrors = false;
    }

    if (deferErrors) {
        // TODO(crbug.com/42240579): ASSERT that encoding only generates validation errors.

        // If the encoding context is not finished, errors are deferred until
        // Finish() is called.
        if (mError == nullptr) {
            mError = std::move(error);
        }
    } else {
        // EncodingContext is unprotected from multiple threads by default, but this code will
        // modify Device's internal states so we need to lock the device now.
        auto deviceGuard = mDevice->GetGuard();
        mDevice->HandleEncoderError(std::move(error));
    }

    CloseWithStatus(Status::ErrorInRecording);
}

void EncodingContext::WillBeginRenderPass() {
    DAWN_CHECK(mCurrentEncoder == mTopLevelEncoder);
    if (mDevice->IsValidationEnabled() || mDevice->MayRequireDuplicationOfIndirectParameters()) {
        // When validation is enabled or indirect parameters require duplication, we are going
        // to want to capture all commands encoded between and including BeginRenderPassCmd and
        // EndRenderPassCmd, and defer their sequencing util after we have a chance to insert
        // any necessary validation or duplication commands. To support this we commit any
        // current commands now, so that the impending BeginRenderPassCmd starts in a fresh
        // CommandAllocator.
        CommitCommands(std::move(mPendingCommands));
    }
}

void EncodingContext::EnterPass(const ApiObjectBase* passEncoder) {
    // Assert we're at the top level.
    DAWN_CHECK(mCurrentEncoder == mTopLevelEncoder);
    DAWN_CHECK(passEncoder != nullptr);

    mCurrentEncoder = passEncoder;
}

MaybeError EncodingContext::ExitRenderPass(const ApiObjectBase* passEncoder,
                                           RenderPassResourceUsageTracker usageTracker,
                                           CommandEncoder* commandEncoder,
                                           IndirectDrawMetadata indirectDrawMetadata) {
    DAWN_CHECK(mCurrentEncoder != mTopLevelEncoder);
    DAWN_CHECK(mCurrentEncoder == passEncoder);

    mCurrentEncoder = mTopLevelEncoder;

    if (mDevice->IsValidationEnabled() || mDevice->MayRequireDuplicationOfIndirectParameters()) {
        // With validation enabled, commands were committed just before BeginRenderPassCmd was
        // encoded by our RenderPassEncoder (see WillBeginRenderPass above). This means
        // mPendingCommands contains only the commands from BeginRenderPassCmd to
        // EndRenderPassCmd, inclusive. Now we swap out this allocator with a fresh one to give
        // the validation encoder a chance to insert its commands first.
        // Note: If encoding validation commands fails, no commands should be in mPendingCommands,
        //       so swap back the renderCommands to ensure that they are not leaked.
        CommandAllocator renderCommands = std::move(mPendingCommands);

        // The below function might create new resources. Device must already be locked via
        // renderpassEncoder's APIEnd().
        // TODO(crbug.com/dawn/1618): In future, all temp resources should be created at
        // Command Submit time, so the locking would be removed from here at that point.
        {
            DAWN_ASSERT(mDevice->IsLockedByCurrentThreadIfNeeded());

            DAWN_TRY_WITH_CLEANUP(
                EncodeIndirectDrawValidationCommands(mDevice, commandEncoder, &usageTracker,
                                                     &indirectDrawMetadata),
                { mPendingCommands = std::move(renderCommands); });
        }

        CommitCommands(std::move(mPendingCommands));
        CommitCommands(std::move(renderCommands));
    }

    mIndirectDrawMetadata.emplace_back(std::move(indirectDrawMetadata));

    mRenderPassUsages.push_back(usageTracker.AcquireResourceUsage());
    return {};
}

void EncodingContext::ExitComputePass(const ApiObjectBase* passEncoder,
                                      ComputePassResourceUsage usages) {
    DAWN_CHECK(mCurrentEncoder != mTopLevelEncoder);
    DAWN_CHECK(mCurrentEncoder == passEncoder);

    mCurrentEncoder = mTopLevelEncoder;
    mComputePassUsages.push_back(std::move(usages));
}

void EncodingContext::EnsurePassExited(const ApiObjectBase* passEncoder) {
    if (mCurrentEncoder != mTopLevelEncoder && mCurrentEncoder == passEncoder) {
        // The current pass encoder is being deleted. Implicitly end the pass with an error.
        mCurrentEncoder = mTopLevelEncoder;
        HandleError(DAWN_VALIDATION_ERROR("Command buffer recording ended before %s was ended.",
                                          passEncoder));
    }
}

const RenderPassUsages& EncodingContext::GetRenderPassUsages() const {
    DAWN_CHECK(!mWereRenderPassUsagesAcquired);
    return mRenderPassUsages;
}

RenderPassUsages EncodingContext::AcquireRenderPassUsages() {
    DAWN_CHECK(!mWereRenderPassUsagesAcquired);
    mWereRenderPassUsagesAcquired = true;
    return std::move(mRenderPassUsages);
}

const ComputePassUsages& EncodingContext::GetComputePassUsages() const {
    DAWN_CHECK(!mWereComputePassUsagesAcquired);
    return mComputePassUsages;
}

ComputePassUsages EncodingContext::AcquireComputePassUsages() {
    DAWN_CHECK(!mWereComputePassUsagesAcquired);
    mWereComputePassUsagesAcquired = true;
    return std::move(mComputePassUsages);
}

ityp::vector<PassIndex, IndirectDrawMetadata> EncodingContext::AcquireIndirectDrawMetadata() {
    DAWN_CHECK(!mWereIndirectDrawMetadataAcquired);
    mWereIndirectDrawMetadataAcquired = true;
    return std::move(mIndirectDrawMetadata);
}

void EncodingContext::PushDebugGroupLabel(std::string_view groupLabel) {
    mDebugGroupLabels.emplace_back(groupLabel);
}

void EncodingContext::PopDebugGroupLabel() {
    mDebugGroupLabels.pop_back();
}

MaybeError EncodingContext::Finish() {
    CommitCommands(std::move(mPendingCommands));

    switch (mStatus) {
        case Status::ErrorAtCreation:
        case Status::Destroyed:
            return {};

        case Status::Finished:
            return DAWN_VALIDATION_ERROR("Command encoding already finished.");

        case Status::ErrorInRecording:
        case Status::Open:
            break;
    }
    const ApiObjectBase* currentEncoder = mCurrentEncoder;
    const ApiObjectBase* topLevelEncoder = mTopLevelEncoder;

    // Even if finish validation fails, it is now invalid to call any encoding commands.
    CloseWithStatus(Status::Finished);

    if (mError != nullptr) {
        return std::move(mError);
    }

    DAWN_INVALID_IF(currentEncoder != topLevelEncoder,
                    "Command buffer recording ended before %s was ended.", currentEncoder);
    return {};
}

void EncodingContext::CommitCommands(CommandAllocator allocator) {
    if (!allocator.IsEmpty()) {
        mAllocators.push_back(std::move(allocator));
    }
}

void EncodingContext::CloseWithStatus(Status status) {
    switch (status) {
        case Status::Open:
        case Status::ErrorAtCreation:
            // We cannot close with Open, and ErrorInRecording is set at construction, never after.
            DAWN_UNREACHABLE();

        // Status::ErrorInRecording causes encoding errors to be silently ignored (as we already
        // have one for this encoder), but both Status::Finished and Status::Destroyed make all
        // further errors surfaced on the device. For that reason we promote a
        // Status::ErrorInRecording to Finished/Destroyed.
        case Status::Destroyed:
        case Status::Finished:
            if (mStatus == Status::ErrorInRecording || mStatus == Status::Open) {
                mStatus = status;
            }
            break;

        case Status::ErrorInRecording:
            if (mStatus == Status::Open) {
                mStatus = status;
            }
            break;
    }

    mTopLevelEncoder = nullptr;
    mCurrentEncoder = nullptr;
}

}  // namespace dawn::native
