// Copyright 2017 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/d3d12/QueueD3D12.h"

#include <limits>
#include <utility>

#include "dawn/platform/DawnPlatform.h"
#include "src/dawn/common/Math.h"
#include "src/dawn/native/CommandValidation.h"
#include "src/dawn/native/Commands.h"
#include "src/dawn/native/DynamicUploader.h"
#include "src/dawn/native/d3d/D3DError.h"
#include "src/dawn/native/d3d12/CommandBufferD3D12.h"
#include "src/dawn/native/d3d12/DeviceD3D12.h"
#include "src/dawn/native/d3d12/SharedFenceD3D12.h"
#include "src/dawn/native/d3d12/UtilsD3D12.h"
#include "src/dawn/platform/tracing/TraceEvent.h"
#include "src/utils/compiler.h"

namespace dawn::native::d3d12 {

// static
ResultOrError<Ref<Queue>> Queue::Create(Device* device, const QueueDescriptor* descriptor) {
    Ref<Queue> queue = AcquireRef(new Queue(device, descriptor));
    DAWN_TRY(queue->Initialize());
    return queue;
}

Queue::~Queue() {}

MaybeError Queue::Initialize() {
    mFreeAllocators.set();

    SetLabelImpl();

    ID3D12Device* d3d12Device = ToBackend(GetDevice())->GetD3D12Device();

    D3D12_COMMAND_QUEUE_DESC queueDesc = {};
    queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
    queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
    DAWN_TRY(CheckHRESULT(d3d12Device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&mCommandQueue)),
                          "D3D12 create command queue"));

    // If PIX is not attached, the QueryInterface fails. Hence, no need to check the return
    // value.
    mCommandQueue.As(&mD3d12SharingContract);

    DAWN_TRY(CheckHRESULT(d3d12Device->CreateFence(uint64_t(kBeginningOfGPUTime),
                                                   D3D12_FENCE_FLAG_SHARED, IID_PPV_ARGS(&mFence)),
                          "D3D12 create fence"));

    DAWN_TRY_ASSIGN(mSharedFence, SharedFence::Create(ToBackend(GetDevice()),
                                                      "Internal shared DXGI fence", mFence));

    return OpenPendingCommands();
}

void Queue::DestroyImpl(DestroyReason reason) {
    // Immediately forget about all pending commands for the case where device is lost on its
    // own and WaitForIdleForDestruction isn't called.
    mPendingCommands.Release();
    mCommandQueue.Reset();

    // Release the shared fence here to prevent a ref-cycle with the device, but do not destroy the
    // underlying native fence so that we can return a SharedFence on EndAccess after destruction.
    mSharedFence = nullptr;
}

ResultOrError<Ref<d3d::SharedFence>> Queue::GetOrCreateSharedFence() {
    if (mSharedFence == nullptr) {
        DAWN_ASSERT(!IsAlive());
        return SharedFence::Create(ToBackend(GetDevice()), "Internal shared DXGI fence", mFence);
    }
    return mSharedFence;
}

ID3D12CommandQueue* Queue::GetCommandQueue() const {
    return mCommandQueue.Get();
}

ID3D12SharingContract* Queue::GetSharingContract() const {
    return mD3d12SharingContract.Get();
}

MaybeError Queue::SubmitImpl(Span<CommandBufferBase* const> commands) {
    CommandRecordingContext* commandContext = GetPendingCommandContext();
    ExecutionSerial pendingSerial = GetPendingCommandSerial();

    TRACE_EVENT_BEGIN1(GetDevice()->GetPlatform(), Recording, "CommandBufferD3D12::RecordCommands",
                       "serial", uint64_t(pendingSerial));
    for (CommandBufferBase* commandBuffer : commands) {
        DAWN_TRY(ToBackend(commandBuffer)->RecordCommands(commandContext));
    }
    TRACE_EVENT_END1(GetDevice()->GetPlatform(), Recording, "CommandBufferD3D12::RecordCommands",
                     "serial", uint64_t(pendingSerial));

    return SubmitPendingCommandsImpl();
}

MaybeError Queue::SubmitPendingCommandsImpl() {
    Device* device = ToBackend(GetDevice());
    DAWN_ASSERT(device->IsLockedByCurrentThreadIfNeeded());

    if (!mPendingCommands.NeedsSubmit()) {
        return {};
    }

    DAWN_TRY(mPendingCommands.ExecuteCommandList(device, mCommandQueue.Get()));
    RecycleLastCommandListAfter(GetPendingCommandSerial());

    // Immediately reopen the command recording context so it is always available.
    DAWN_TRY(NextSerial());
    DAWN_TRY(RecycleUnusedCommandLists());
    return OpenPendingCommands();
}

MaybeError Queue::NextSerial() {
    Device* device = ToBackend(GetDevice());
    DAWN_ASSERT(device->IsLockedByCurrentThreadIfNeeded());
    // NextSerial should not ever be called with a command list that needs submission since the
    // underlying command allocator could be recycled after the serial completes on the GPU.
    DAWN_ASSERT(!mPendingCommands.NeedsSubmit());

    IncrementLastSubmittedCommandSerial();

    TRACE_EVENT1(device->GetPlatform(), General, "D3D12Device::SignalFence", "serial",
                 uint64_t(GetLastSubmittedCommandSerial()));

    return CheckHRESULT(
        mCommandQueue->Signal(mFence.Get(), uint64_t(GetLastSubmittedCommandSerial())),
        "D3D12 command queue signal fence");
}

MaybeError Queue::WaitForSerial(ExecutionSerial serial) {
    if (GetCompletedCommandSerial() >= serial) {
        return {};
    }
    DAWN_TRY_ASSIGN(std::ignore,
                    WaitForQueueSerialImpl(serial, std::numeric_limits<Nanoseconds>::max()));
    return CheckPassedSerials();
}

bool Queue::HasPendingCommands() const {
    return mPendingCommands.NeedsSubmit();
}

ResultOrError<ExecutionSerial> Queue::CheckAndUpdateCompletedSerials() {
    // TODO(crbug.com/40643114): Revisit whether this lock is needed for this backend.
    auto deviceGuard = GetDevice()->GetGuard();

    ExecutionSerial completedSerial = ExecutionSerial(mFence->GetCompletedValue());
    if (completedSerial == ExecutionSerial(UINT64_MAX)) [[unlikely]] {
        // GetCompletedValue returns UINT64_MAX if the device was removed.
        // Try to query the failure reason.
        ID3D12Device* d3d12Device = ToBackend(GetDevice())->GetD3D12Device();
        DAWN_TRY(CheckHRESULT(d3d12Device->GetDeviceRemovedReason(),
                              "ID3D12Device::GetDeviceRemovedReason"));
        // Otherwise, return a generic device lost error.
        return DAWN_DEVICE_LOST_ERROR("Device lost");
    }

    if (completedSerial <= GetCompletedCommandSerial()) {
        return ExecutionSerial(0u);
    }

    DAWN_TRY(RecycleSystemEventReceivers(completedSerial));

    return completedSerial;
}

void Queue::ForceEventualFlushOfCommands() {
    mPendingCommands.SetNeedsSubmit();
}

MaybeError Queue::WaitForIdleForDestructionImpl() {
    // Immediately forget about all pending commands
    mPendingCommands.Release();

    // Wait for all in-flight commands to finish executing and clean
    DAWN_TRY(NextSerial());
    DAWN_TRY(WaitForSerial(GetLastSubmittedCommandSerial()));

    // Clean up after waiting for the commands.
    return RecycleUnusedCommandLists();
}

CommandRecordingContext* Queue::GetPendingCommandContext(SubmitMode submitMode) {
    if (submitMode == SubmitMode::Normal) {
        mPendingCommands.SetNeedsSubmit();
    }
    return &mPendingCommands;
}

void Queue::SetLabelImpl() {
    Device* device = ToBackend(GetDevice());
    // TODO(crbug.com/dawn/1344): When we start using multiple queues this needs to be adjusted
    // so it doesn't always change the default queue's label.
    SetDebugName(device, mCommandQueue.Get(), "Dawn_Queue", GetLabel());
}

void Queue::SetEventOnCompletion(ExecutionSerial serial, HANDLE event) {
    mFence->SetEventOnCompletion(static_cast<uint64_t>(serial), event);
}

MaybeError Queue::OpenPendingCommands() {
    DAWN_ASSERT(mLastAllocatorUsed == kNoCommandAllocator);

    // If there are no free allocators, get the oldest serial in flight and wait on it
    if (mFreeAllocators.none()) {
        const ExecutionSerial firstSerial = mInFlightCommandAllocators.FirstSerial();
        DAWN_TRY(WaitForSerial(firstSerial));
        DAWN_TRY(RecycleUnusedCommandLists());
    }

    // This is a release check to catch a potential issue where allocator recycling didn't seem to
    // work correctly so we want to get crash reports if it happens again.
    DAWN_CHECK(mFreeAllocators.any());
    ID3D12Device* d3d12Device = ToBackend(GetDevice())->GetD3D12Device();

    // Get the index of the first free allocator from the bitset
    uint32_t freeIndex = *(mFreeAllocators).begin();
    mFreeAllocators.reset(freeIndex);
    auto& allocator = mCommandAllocators[freeIndex];

    // Lazily create an allocator or reset an existing one to start a new command list on it.
    if (freeIndex >= mAllocatorCount) {
        DAWN_ASSERT(freeIndex == mAllocatorCount);
        mAllocatorCount++;

        DAWN_TRY(
            CheckHRESULT(d3d12Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT,
                                                             IID_PPV_ARGS(&allocator.allocator)),
                         "D3D12 create command allocator"));
        DAWN_TRY(CheckHRESULT(d3d12Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT,
                                                             allocator.allocator.Get(), nullptr,
                                                             IID_PPV_ARGS(&allocator.list)),
                              "D3D12 creating direct command list"));
    } else {
        DAWN_TRY(CheckHRESULT(allocator.list->Reset(allocator.allocator.Get(), nullptr),
                              "D3D12 resetting command list"));
    }

    mLastAllocatorUsed = freeIndex;
    mPendingCommands.Open(mCommandAllocators[mLastAllocatorUsed].list);
    return {};
}

void Queue::RecycleLastCommandListAfter(ExecutionSerial serial) {
    mInFlightCommandAllocators.Enqueue(mLastAllocatorUsed, serial);
    mLastAllocatorUsed = kNoCommandAllocator;
}

MaybeError Queue::RecycleUnusedCommandLists() {
    ExecutionSerial completedSerial = GetCompletedCommandSerial();
    for (auto index : mInFlightCommandAllocators.IterateUpTo(completedSerial)) {
        DAWN_TRY(CheckHRESULT(mCommandAllocators[index].allocator->Reset(),
                              "D3D12 reset command allocator"));
        mFreeAllocators.set(index);
    }
    mInFlightCommandAllocators.ClearUpTo(completedSerial);

    return {};
}

}  // namespace dawn::native::d3d12
