// Copyright 2023 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/d3d11/QueueD3D11.h"

#include <algorithm>
#include <chrono>
#include <deque>
#include <iterator>
#include <limits>
#include <thread>
#include <utility>
#include <vector>

#include "absl/container/inlined_vector.h"
#include "dawn/platform/DawnPlatform.h"
#include "src/dawn/native/WaitAnySystemEvent.h"
#include "src/dawn/native/d3d/D3DError.h"
#include "src/dawn/native/d3d11/BufferD3D11.h"
#include "src/dawn/native/d3d11/CommandBufferD3D11.h"
#include "src/dawn/native/d3d11/DeviceD3D11.h"
#include "src/dawn/native/d3d11/DeviceInfoD3D11.h"
#include "src/dawn/native/d3d11/PhysicalDeviceD3D11.h"
#include "src/dawn/native/d3d11/SharedFenceD3D11.h"
#include "src/dawn/native/d3d11/TextureD3D11.h"
#include "src/dawn/platform/tracing/TraceEvent.h"
#include "src/utils/compiler.h"
#include "src/utils/log.h"
#include "src/utils/numeric.h"

namespace dawn::native::d3d11 {
namespace {

// Queue's subclass that uses monitored fences exclusively to signal/track work done.
class MonitoredFenceQueue final : public Queue {
  public:
    using Queue::Queue;
    MaybeError Initialize();
    MaybeError NextSerial() override;
    ResultOrError<ExecutionSerial> CheckCompletedSerialsImpl() override;
    void SetEventOnCompletion(ExecutionSerial serial, HANDLE event) override;

  private:
    ~MonitoredFenceQueue() override = default;
};

// Queue's subclass that uses SystemEvent + Flush1 to track work done.
class SystemEventQueue final : public Queue {
  public:
    using Queue::Queue;
    MaybeError Initialize();
    MaybeError NextSerial() override;
    ResultOrError<ExecutionSerial> CheckCompletedSerialsImpl() override;
    ResultOrError<ExecutionSerial> WaitForQueueSerialImpl(ExecutionSerial serial,
                                                          Nanoseconds timeout) override;
    void SetEventOnCompletion(ExecutionSerial serial, HANDLE event) override;

  private:
    ~SystemEventQueue() override = default;

    struct SerialEventReceiverPair {
        ExecutionSerial serial;
        SystemEventReceiver receiver;
    };
    // Events associated with submitted commands. They are in old to recent order.
    MutexProtected<std::deque<SerialEventReceiverPair>> mPendingEvents;

    // List of completed events to be recycled in CheckCompletedSerialsImpl().
    MutexProtected<std::vector<SerialEventReceiverPair>> mCompletedEvents;
};

// Queue's subclass that doesn't flush the commands to GPU immediately in Submit().
// This class uses ID3D11Query to track a serial's work completion. ID3D11Query::GetData() can be
// used to check whether the serial has passed or not.
// Note that if the commands were never sent to the GPU, ID3D11Query::GetData() might never return
// true and the application might wait indefinitely for a serial to complete. Thus, a flush must be
// triggered implicitly at some points. For the current implementation, a flush will be triggered
// when one of the following conditions is met:
// - Application calls IDXGISwapChain::Present() either via SwapChain class or externally.
// - Application calls WaitAny() to wait for a GPU operation/buffer mapping to finish.
// - ID3D11Query::GetData() has been called N times. This can be triggered indirectly via:
//   - Calling Device::Tick() or Queue::Submit() N times.
//   - Both the above methods indirectly trigger CheckAndUpdateCompletedSerials() which in turn
//   calls ID3D11Query::GetData() N times.
class DelayFlushQueue final : public Queue {
  public:
    using Queue::Queue;
    MaybeError Initialize();
    MaybeError NextSerial() override;
    ResultOrError<ExecutionSerial> CheckCompletedSerialsImpl() override;
    ResultOrError<ExecutionSerial> WaitForQueueSerialImpl(ExecutionSerial serial,
                                                          Nanoseconds timeout) override;
    void SetEventOnCompletion(ExecutionSerial serial, HANDLE event) override;

  private:
    ~DelayFlushQueue() override = default;

    // Check for completed serials in the pending list.
    MaybeError CheckPendingQueries(const ScopedCommandRecordingContext* commandContext);

    void MarkPendingQueriesAsComplete(size_t numCompletedQueries);

    MaybeError BlockWaitForLastSubmittedSerial(const ScopedCommandRecordingContext* commandContext);

    struct EventQuery {
      public:
        EventQuery(ExecutionSerial serial, ComPtr<ID3D11Query> query)
            : mSerial(serial), mQuery(std::move(query)) {}

        ExecutionSerial Serial() const { return mSerial; }
        ComPtr<ID3D11Query> AcquireQuery() { return std::move(mQuery); }
        ID3D11Query* GetQuery() { return mQuery.Get(); }

        // Number of GetData() calls on this query.
        size_t checkCount = 0;

      private:
        ExecutionSerial mSerial;
        ComPtr<ID3D11Query> mQuery;
    };

    ResultOrError<bool> IsQueryCompleted(const ScopedCommandRecordingContext* commandContext,
                                         bool requireFlush,
                                         EventQuery* eventQuery);

    // Events associated with submitted commands. They are in old to recent order.
    std::deque<EventQuery> mPendingQueries;
    // List of completed queries to be recycled in CheckCompletedSerialsImpl().
    std::vector<EventQuery> mCompletedQueries;
    // List of recycled queries.
    std::vector<ComPtr<ID3D11Query>> mFreeQueries;
};

}  // namespace

ResultOrError<Ref<Queue>> Queue::Create(Device* device, const QueueDescriptor* descriptor) {
    const auto& deviceInfo = ToBackend(device->GetPhysicalDevice())->GetDeviceInfo();
    if (device->IsToggleEnabled(Toggle::D3D11DelayFlushToGPU)) {
        auto queue = AcquireRef(new DelayFlushQueue(device, descriptor));
        DAWN_TRY(queue->Initialize());
        return queue;
    }

    if (device->IsToggleEnabled(Toggle::D3D11UseUnmonitoredFence) ||
        device->IsToggleEnabled(Toggle::D3D11DisableFence)) {
        auto queue = AcquireRef(new SystemEventQueue(device, descriptor));
        DAWN_TRY(queue->Initialize());
        return queue;
    }

    DAWN_ASSERT(deviceInfo.supportsMonitoredFence);
    auto queue = AcquireRef(new MonitoredFenceQueue(device, descriptor));
    DAWN_TRY(queue->Initialize());
    return queue;
}

MaybeError Queue::Initialize(bool useNonMonitoredFence) {
    if (!GetDevice()->IsToggleEnabled(Toggle::D3D11DisableFence)) {
        DAWN_TRY(InitializeD3DFence(useNonMonitoredFence));
    }

    return {};
}

MaybeError Queue::InitializeD3DFence(bool useNonMonitoredFence) {
    const auto& deviceInfo = ToBackend(GetDevice()->GetPhysicalDevice())->GetDeviceInfo();

    // Create the fence.
    D3D11_FENCE_FLAG flags = D3D11_FENCE_FLAG_SHARED;
    if (useNonMonitoredFence) {
        if (deviceInfo.supportsNonMonitoredFence) {
            flags |= D3D11_FENCE_FLAG_NON_MONITORED;
            // For adapters that support both monitored and non-monitored fences, non-monitored
            // fences are only supported when created with the D3D12_FENCE_FLAG_SHARED and
            // D3D12_FENCE_FLAG_SHARED_CROSS_ADAPTER flags
            // https://learn.microsoft.com/en-us/windows/win32/api/dxgi1_6/ne-dxgi1_6-dxgi_adapter_flag3
            if (deviceInfo.supportsMonitoredFence) {
                flags |= D3D11_FENCE_FLAG_SHARED_CROSS_ADAPTER;
            }
        } else {
            WarningLog()
                << "D3D11: non-monitored fence is not supported, fallback to monitored fence";
        }
    } else {
        DAWN_ASSERT(deviceInfo.supportsMonitoredFence);
    }
    DAWN_TRY(CheckHRESULT(
        ToBackend(GetDevice())->GetD3D11Device5()->CreateFence(0, flags, IID_PPV_ARGS(&mFence)),
        useNonMonitoredFence ? "D3D11: creating non-monitored fence"
                             : "D3D11: creating monitored fence"));

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

    return {};
}

MaybeError Queue::InitializePendingContext() {
    // Initialize mPendingCommands. After this, calls to the use the command context
    // are thread safe.
    CommandRecordingContext commandContext;
    DAWN_TRY(commandContext.Initialize(ToBackend(GetDevice())));

    mPendingCommands.Use(
        [&](auto pendingCommandContext) { *pendingCommandContext = std::move(commandContext); });

    // Configure the command context's uniform buffer. This is used to emulate builtins.
    // Creating the buffer is done outside of Initialize because it requires mPendingCommands
    // to already be initialized.
    Ref<BufferBase> uniformBuffer;
    DAWN_TRY_ASSIGN(uniformBuffer,
                    CommandRecordingContext::CreateInternalUniformBuffer(GetDevice()));

    {
        auto persistentCommandContext =
            GetScopedSwapStatePendingCommandContext(SubmitMode::Passive);
        DAWN_TRY(persistentCommandContext.SetInternalUniformBuffer(std::move(uniformBuffer)));
    }

    return {};
}

void Queue::DestroyImpl(DestroyReason reason) {
    // 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;

    mPendingCommands.Use([&](auto pendingCommands) {
        pendingCommands->Destroy();
        mPendingCommandsNeedSubmit.store(false, std::memory_order_release);
    });
}

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

template <typename ScopedContextType, typename... Args>
ScopedContextType Queue::CreateScopedCommandContext(SubmitMode submitMode,
                                                    CommandRecordingContext::Guard&& commands,
                                                    Args&&... args) {
    if (submitMode == SubmitMode::Normal) {
        mPendingCommandsNeedSubmit.store(true, std::memory_order_release);
    }
    return ScopedContextType(std::move(commands), std::forward<Args>(args)...);
}

ScopedCommandRecordingContext Queue::GetScopedPendingCommandContext(SubmitMode submitMode,
                                                                    bool lockD3D11Scope) {
    return mPendingCommands.Use([&](auto commands) -> ScopedCommandRecordingContext {
        return CreateScopedCommandContext<ScopedCommandRecordingContext>(
            submitMode, std::move(commands), lockD3D11Scope);
    });
}

std::optional<ScopedCommandRecordingContext> Queue::TryGetScopedPendingCommandContext(
    SubmitMode submitMode,
    bool lockD3D11Scope) {
    std::optional<CommandRecordingContext::Guard> guard = mPendingCommands.TryUse();
    if (!guard) {
        return std::nullopt;
    }
    return CreateScopedCommandContext<ScopedCommandRecordingContext>(submitMode, std::move(*guard),
                                                                     lockD3D11Scope);
}

ScopedSwapStateCommandRecordingContext Queue::GetScopedSwapStatePendingCommandContext(
    SubmitMode submitMode) {
    return mPendingCommands.Use([&](auto commands) {
        return CreateScopedCommandContext<ScopedSwapStateCommandRecordingContext>(
            submitMode, std::move(commands));
    });
}

MaybeError Queue::SubmitPendingCommandsImpl() {
    bool needsSubmit = mPendingCommands.Use([&](auto pendingCommands) {
        pendingCommands->ReleaseKeyedMutexes();
        return mPendingCommandsNeedSubmit.exchange(false, std::memory_order_acq_rel);
    });
    if (needsSubmit) {
        return NextSerial();
    }
    return {};
}

MaybeError Queue::SubmitImpl(Span<CommandBufferBase* const> commands) {
    // CommandBuffer::Execute() will modify the state of the global immediate device context, it may
    // affect following usage of it.
    // TODO(dawn:1770): figure how if we need to track and restore the state of the immediate device
    // context.
    TRACE_EVENT_BEGIN0(GetDevice()->GetPlatform(), Recording, "CommandBufferD3D11::Execute");
    {
        auto commandContext =
            GetScopedSwapStatePendingCommandContext(QueueBase::SubmitMode::Normal);
        for (CommandBufferBase* commandBuffer : commands) {
            DAWN_TRY(ToBackend(commandBuffer)->Execute(&commandContext));
        }
    }
    DAWN_TRY(SubmitPendingCommandsImpl());
    TRACE_EVENT_END0(GetDevice()->GetPlatform(), Recording, "CommandBufferD3D11::Execute");

    return {};
}

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

    if (!mPendingCommands->IsValid()) {
        // Device might already be destroyed. Skip checking further.
        return GetCompletedCommandSerial();
    }

    ExecutionSerial completedSerial;

    DAWN_TRY_ASSIGN(completedSerial, CheckCompletedSerialsImpl());

    // Finalize Mapping on ready buffers.
    DAWN_TRY(CheckScheduledBufferMappings(completedSerial));

    return completedSerial;
}

MaybeError Queue::CheckScheduledBufferMappings(ExecutionSerial completedSerial) {
    auto commandContext = GetScopedPendingCommandContext(QueueBase::SubmitMode::Passive);
    return mPendingMapBuffers.Use([&](auto pendingMapBuffers) -> MaybeError {
        auto& serialQueue = pendingMapBuffers->serialQueue;
        auto& requestMap = pendingMapBuffers->requestMap;

        // Process all serials up to and including completedSerial
        auto it = serialQueue.begin();
        while (it != serialQueue.end() && it->first <= completedSerial) {
            LinkedList<BufferMapRequest>& list = it->second;

            // Process all buffers in this serial's list
            while (!list.empty()) {
                LinkNode<BufferMapRequest>* node = list.head();
                BufferMapRequest* request = node->value();
                Buffer* buffer = request->buffer;

                DAWN_ASSERT(buffer);
                DAWN_TRY(buffer->TryMapNow(&commandContext, completedSerial, request->mode));

                request->RemoveFromList();
                requestMap.erase(buffer);
            }

            // Erase this serial's entry and advance iterator
            it = serialQueue.erase(it);
        }

        return {};
    });
}

void Queue::ScheduleBufferMapping(BufferMapRequest* request, ExecutionSerial readySerial) {
    DAWN_ASSERT(request->buffer != nullptr);
    mPendingMapBuffers.Use([&](auto pendingMapBuffers) {
        auto& serialQueue = pendingMapBuffers->serialQueue;
        auto& requestMap = pendingMapBuffers->requestMap;

        auto& storedRequest = requestMap[request->buffer];
        // Cancel old schedule if any. This is because we only allow one schedule per buffer.
        // Any new schedule will overwrite the old one.
        if (storedRequest) {
            storedRequest->RemoveFromList();
        }
        storedRequest = request;

        DAWN_ASSERT(!request->IsInList());
        serialQueue[readySerial].Append(request);
    });
}

void Queue::CancelScheduledBufferMapping(Buffer* buffer) {
    mPendingMapBuffers.Use([&](auto pendingMapBuffers) {
        auto& requestMap = pendingMapBuffers->requestMap;

        auto it = requestMap.find(buffer);
        if (it != requestMap.end()) {
            BufferMapRequest* entry = it->second;
            entry->RemoveFromList();
            requestMap.erase(it);
        }
    });
}

MaybeError Queue::WriteBufferImpl(BufferBase* buffer,
                                  uint64_t bufferOffset,
                                  Span<const std::byte> data) {
    if (data.empty()) {
        // skip the empty write
        return {};
    }

    auto commandContext = GetScopedPendingCommandContext(QueueBase::SubmitMode::Normal);
    return ToBackend(buffer)->Write(&commandContext, bufferOffset, data.data(), data.size());
}

MaybeError Queue::WriteTextureImpl(const TexelCopyTextureInfo& destination,
                                   Span<const std::byte> data,
                                   const TexelCopyBufferLayout& dataLayout,
                                   const Extent3D& writeSizePixel) {
    if (writeSizePixel.width == 0 || writeSizePixel.height == 0 ||
        writeSizePixel.depthOrArrayLayers == 0) {
        return {};
    }

    auto commandContext = GetScopedPendingCommandContext(QueueBase::SubmitMode::Normal);
    TextureCopy textureCopy;
    textureCopy.texture = destination.texture;
    textureCopy.mipLevel = destination.mipLevel;
    textureCopy.origin = destination.origin;
    textureCopy.aspect = SelectFormatAspects(destination.texture->GetFormat(), destination.aspect);

    SubresourceRange subresources = GetSubresourcesAffectedByCopy(textureCopy, writeSizePixel);

    Texture* texture = ToBackend(destination.texture);
    DAWN_TRY(texture->SynchronizeTextureBeforeUse(&commandContext));
    return texture->Write(
        &commandContext, subresources, destination.origin, writeSizePixel,
        DAWN_UNSAFE_TODO(reinterpret_cast<const uint8_t*>(data.data()) + dataLayout.offset),
        dataLayout.bytesPerRow, dataLayout.rowsPerImage);
}

bool Queue::HasPendingCommands() const {
    return mPendingCommandsNeedSubmit.load(std::memory_order_acquire);
}

void Queue::ForceEventualFlushOfCommands() {
    mPendingCommandsNeedSubmit.store(true, std::memory_order_release);
}

MaybeError Queue::WaitForIdleForDestructionImpl() {
    if (!mPendingCommands->IsValid()) {
        return {};
    }

    DAWN_TRY(NextSerial());
    // Wait for all in-flight commands to finish executing
    DAWN_TRY_ASSIGN(std::ignore, WaitForQueueSerialImpl(GetLastSubmittedCommandSerial(),
                                                        std::numeric_limits<Nanoseconds>::max()));
    return CheckPassedSerials();
}

// MonitoredFenceQueue:
MaybeError MonitoredFenceQueue::Initialize() {
    return Queue::Initialize(/*useNonMonitoredFence=*/false);
}

MaybeError MonitoredFenceQueue::NextSerial() {
    auto commandContext = GetScopedPendingCommandContext(SubmitMode::Passive);

    DAWN_TRY(commandContext.FlushBuffersForSyncingWithCPU());

    const uint64_t submitSerial = uint64_t(GetPendingCommandSerial());

    {
        TRACE_EVENT1(GetDevice()->GetPlatform(), General, "D3D11Device::SignalFence", "serial",
                     submitSerial);
        DAWN_TRY(CheckHRESULT(commandContext.Signal(mFence.Get(), submitSerial),
                              "D3D11 command queue signal fence"));
    }

    IncrementLastSubmittedCommandSerial();

    return {};
}

ResultOrError<ExecutionSerial> MonitoredFenceQueue::CheckCompletedSerialsImpl() {
    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.
        ID3D11Device* d3d11Device = ToBackend(GetDevice())->GetD3D11Device();
        DAWN_TRY(CheckHRESULT(d3d11Device->GetDeviceRemovedReason(),
                              "ID3D11Device::GetDeviceRemovedReason"));
        // Otherwise, return a generic device lost error.
        return DAWN_DEVICE_LOST_ERROR("Device lost");
    }

    DAWN_TRY(RecycleSystemEventReceivers(completedSerial));

    return completedSerial;
}

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

// SystemEventQueue:
MaybeError SystemEventQueue::Initialize() {
    return Queue::Initialize(
        /*useNonMonitoredFence=*/GetDevice()->IsToggleEnabled(Toggle::D3D11UseUnmonitoredFence));
}

MaybeError SystemEventQueue::NextSerial() {
    auto commandContext = GetScopedPendingCommandContext(SubmitMode::Passive);

    DAWN_TRY(commandContext.FlushBuffersForSyncingWithCPU());

    const ExecutionSerial submitSerial = GetPendingCommandSerial();
    if (commandContext->AcquireNeedsFence()) {
        DAWN_ASSERT(mFence);

        TRACE_EVENT1(GetDevice()->GetPlatform(), General, "D3D11Device::SignalFence", "serial",
                     uint64_t(submitSerial));
        DAWN_TRY(CheckHRESULT(commandContext.Signal(mFence.Get(), uint64_t(submitSerial)),
                              "D3D11 command queue signal fence"));
    }

    SystemEventReceiver receiver;
    DAWN_TRY_ASSIGN(receiver, GetSystemEventReceiver());
    commandContext.Flush1(D3D11_CONTEXT_TYPE_ALL, receiver.GetPrimitive().Get());
    mPendingEvents->push_back({submitSerial, std::move(receiver)});

    IncrementLastSubmittedCommandSerial();

    return {};
}

ResultOrError<ExecutionSerial> SystemEventQueue::CheckCompletedSerialsImpl() {
    ExecutionSerial completedSerial;
    std::vector<SystemEventReceiver> returnedReceivers;
    // Check for completed events in the pending list.
    DAWN_TRY_ASSIGN(
        completedSerial,
        mPendingEvents.Use([&](auto pendingEvents) -> ResultOrError<ExecutionSerial> {
            if (pendingEvents->empty()) {
                return GetLastSubmittedCommandSerial();
            }

            absl::InlinedVector<HANDLE, 8> handles;
            const size_t numberOfHandles =
                std::min(pendingEvents->size(), static_cast<size_t>(MAXIMUM_WAIT_OBJECTS));
            handles.reserve(numberOfHandles);
            // Gather events in reversed order (from the most recent to the oldest events).
            std::for_each_n(pendingEvents->rbegin(), numberOfHandles, [&handles](const auto& e) {
                handles.push_back(e.receiver.GetPrimitive().Get());
            });
            DWORD result =
                WaitForMultipleObjects(handles.size(), handles.data(), /*bWaitAll=*/false,
                                       /*dwMilliseconds=*/0);
            DAWN_INTERNAL_ERROR_IF(result == WAIT_FAILED, "WaitForMultipleObjects() failed");

            DAWN_INTERNAL_ERROR_IF(
                result >= WAIT_ABANDONED_0 && result < WAIT_ABANDONED_0 + handles.size(),
                "WaitForMultipleObjects() get abandoned event");

            if (result == WAIT_TIMEOUT) {
                return GetCompletedCommandSerial();
            }

            DAWN_CHECK(result >= WAIT_OBJECT_0 && result < WAIT_OBJECT_0 + pendingEvents->size());
            const size_t completedEventIndex = result - WAIT_OBJECT_0;
            // |WaitForMultipleObjects()| returns the smallest index, if more than one
            // events are signalled. So the number of completed events are
            // |mPendingEvents.size() - index|.
            const size_t completedEvents = pendingEvents->size() - completedEventIndex;
            auto completedSerial = pendingEvents->at(completedEvents - 1).serial;
            returnedReceivers.reserve(completedEvents);
            std::for_each_n(pendingEvents->begin(), completedEvents, [&returnedReceivers](auto& e) {
                returnedReceivers.emplace_back(std::move(e.receiver));
            });
            pendingEvents->erase(pendingEvents->begin(),
                                 pendingEvents->begin() + sign_cast(completedEvents));

            return completedSerial;
        }));

    // Also check for completed events processed by WaitForQueueSerialImpl()
    mCompletedEvents.Use([&](auto completedEvents) {
        returnedReceivers.reserve(returnedReceivers.size() + completedEvents->size());
        for (auto& event : *completedEvents) {
            completedSerial = std::max(completedSerial, event.serial);
            returnedReceivers.emplace_back(std::move(event.receiver));
        }
        completedEvents->clear();
    });

    if (!returnedReceivers.empty()) {
        DAWN_TRY(ReturnSystemEventReceivers(
            std::span(returnedReceivers.data(), returnedReceivers.size())));
    }

    return completedSerial;
}

ResultOrError<ExecutionSerial> SystemEventQueue::WaitForQueueSerialImpl(ExecutionSerial serial,
                                                                        Nanoseconds timeout) {
    ExecutionSerial completedSerial = GetCompletedCommandSerial();
    if (serial <= completedSerial) {
        return serial;
    }

    if (serial > GetLastSubmittedCommandSerial()) {
        return DAWN_FORMAT_INTERNAL_ERROR(
            "Wait a serial (%llu) which is greater than last submitted command serial (%llu).",
            uint64_t(serial), uint64_t(GetLastSubmittedCommandSerial()));
    }

    return mPendingEvents.Use([=, &completedEventsList = mCompletedEvents](
                                  auto pendingEvents) -> ResultOrError<ExecutionSerial> {
        DAWN_ASSERT(!pendingEvents->empty());
        DAWN_ASSERT(serial >= pendingEvents->front().serial);
        DAWN_ASSERT(serial <= pendingEvents->back().serial);
        auto it = std::lower_bound(
            pendingEvents->begin(), pendingEvents->end(), serial,
            [](const SerialEventReceiverPair& a, ExecutionSerial b) { return a.serial < b; });
        DAWN_ASSERT(it != pendingEvents->end());
        DAWN_ASSERT(it->serial == serial);

        // TODO(crbug.com/335553337): call WaitForSingleObject() without holding the mutex.
        DWORD result =
            WaitForSingleObject(it->receiver.GetPrimitive().Get(), ToMilliseconds(timeout));
        DAWN_INTERNAL_ERROR_IF(result == WAIT_FAILED, "WaitForSingleObject() failed");

        if (result != WAIT_OBJECT_0) {
            return kWaitSerialTimeout;
        }

        // Events before |it| should be signalled as well.
        completedEventsList.Use([&](auto completedEvList) {
            completedEvList->insert(completedEvList->end(),
                                    std::make_move_iterator(pendingEvents->begin()),
                                    std::make_move_iterator(it + 1));
        });
        pendingEvents->erase(pendingEvents->begin(), it + 1);

        return serial;
    });
}

void SystemEventQueue::SetEventOnCompletion(ExecutionSerial serial, HANDLE event) {
    DAWN_UNREACHABLE();
}

// DelayFlushQueue:
MaybeError DelayFlushQueue::Initialize() {
    return Queue::Initialize(
        /*useNonMonitoredFence=*/GetDevice()->IsToggleEnabled(Toggle::D3D11UseUnmonitoredFence));
}

MaybeError DelayFlushQueue::NextSerial() {
    auto commandContext = GetScopedPendingCommandContext(SubmitMode::Passive);

    DAWN_TRY(commandContext.FlushBuffersForSyncingWithCPU());

    ExecutionSerial submitSerial = GetPendingCommandSerial();

    ComPtr<ID3D11Query> query;

    if (!mFreeQueries.empty()) {
        query = std::move(mFreeQueries.back());
        mFreeQueries.pop_back();
    } else {
        D3D11_QUERY_DESC queryDesc = {};
        queryDesc.Query = D3D11_QUERY_EVENT;
        DAWN_TRY(
            CheckHRESULT(ToBackend(GetDevice())->GetD3D11Device3()->CreateQuery(&queryDesc, &query),
                         "CreateQuery"));
    }

    commandContext.End(query.Get());

    if (commandContext->AcquireNeedsFence()) {
        DAWN_ASSERT(mFence);

        TRACE_EVENT1(GetDevice()->GetPlatform(), General, "D3D11Device::SignalFence", "serial",
                     uint64_t(submitSerial));
        DAWN_TRY(CheckHRESULT(commandContext.Signal(mFence.Get(), uint64_t(submitSerial)),
                              "D3D11 command queue signal fence"));
    }

    mPendingQueries.emplace_back(submitSerial, std::move(query));

    IncrementLastSubmittedCommandSerial();

    return {};
}

MaybeError DelayFlushQueue::CheckPendingQueries(
    const ScopedCommandRecordingContext* commandContext) {
    if (mPendingQueries.empty()) {
        return {};
    }

    // Check queries' status starting from oldest to most recent.
    // TODO(416736350): Consider using a binary search.
    size_t completedQueriesCount = 0;
    for (size_t i = 0; i < mPendingQueries.size(); ++i) {
        bool done;
        DAWN_TRY_ASSIGN(
            done, IsQueryCompleted(commandContext, /*requireFlush=*/false, &mPendingQueries[i]));
        if (!done) {
            // We stop at 1st incompleted query.
            break;
        }
        completedQueriesCount++;
    }

    if (completedQueriesCount == 0) {
        return {};
    }

    MarkPendingQueriesAsComplete(completedQueriesCount);

    return {};
}

ResultOrError<ExecutionSerial> DelayFlushQueue::CheckCompletedSerialsImpl() {
    ExecutionSerial completedSerial;
    {
        auto commandContext = GetScopedPendingCommandContext(SubmitMode::Passive);

        completedSerial = GetCompletedCommandSerial();

        DAWN_TRY(CheckPendingQueries(&commandContext));

        for (auto& e : mCompletedQueries) {
            completedSerial = std::max(completedSerial, e.Serial());
            mFreeQueries.emplace_back(e.AcquireQuery());
        }
        mCompletedQueries.clear();
    }

    return completedSerial;
}

ResultOrError<ExecutionSerial> DelayFlushQueue::WaitForQueueSerialImpl(ExecutionSerial waitSerial,
                                                                       Nanoseconds timeout) {
    ExecutionSerial completedSerial = GetCompletedCommandSerial();
    if (waitSerial <= completedSerial) {
        return waitSerial;
    }

    if (waitSerial > GetLastSubmittedCommandSerial()) {
        return DAWN_FORMAT_INTERNAL_ERROR(
            "Wait a serial (%llu) which is greater than last submitted command serial (%llu).",
            uint64_t(waitSerial), uint64_t(GetLastSubmittedCommandSerial()));
    }

    // A coarse-grained D3D11 scope lock is unnecessary here. When D3D11 multithread protection is
    // enabled, calls to ID3D11DeviceContext::GetData() are already implicitly lock-protected. This
    // function polls for completion by repeatedly calling GetData(). Holding a scope lock for the
    // entire polling duration would be inefficient and could lead to deadlocks if the driver
    // attempts to acquire the same lock internally.
    auto commandContext =
        GetScopedPendingCommandContext(SubmitMode::Passive, /*lockD3D11Scope=*/false);

    if (mPendingQueries.empty() || waitSerial < mPendingQueries.front().Serial()) {
        // Empty list must mean the serial have already completed.
        return waitSerial;
    }

    if (uint64_t(timeout) == std::numeric_limits<uint64_t>::max() &&
        waitSerial == GetLastSubmittedCommandSerial()) {
        // If user submits then waits immediately, we can do a small optimization here,
        // Flush + enqueue SetEvent then wait on the event. This can avoid spinning wait below,
        // wasting less CPU cycles.
        DAWN_TRY(BlockWaitForLastSubmittedSerial(&commandContext));
    }

    DAWN_ASSERT(waitSerial >= mPendingQueries.front().Serial());
    DAWN_ASSERT(waitSerial <= mPendingQueries.back().Serial());
    auto it =
        std::lower_bound(mPendingQueries.begin(), mPendingQueries.end(), waitSerial,
                         [](const EventQuery& a, ExecutionSerial b) { return a.Serial() < b; });
    DAWN_ASSERT(it != mPendingQueries.end());
    DAWN_ASSERT(it->Serial() == waitSerial);

    bool done;
    DAWN_TRY_ASSIGN(done, IsQueryCompleted(&commandContext, /*requireFlush=*/false, &(*it)));
    if (timeout == Nanoseconds(0u)) {
        if (!done) {
            // Return timed-out immediately without using a timer.
            return kWaitSerialTimeout;
        }
    } else {
        auto startTime = std::chrono::steady_clock::now();

        while (!done) {
            DAWN_TRY_ASSIGN(done, IsQueryCompleted(&commandContext, /*requireFlush=*/true, &(*it)));

            if (!done) {
                auto curTime = std::chrono::steady_clock::now();
                auto elapsedNs =
                    std::chrono::duration_cast<std::chrono::nanoseconds>(curTime - startTime);
                if (static_cast<uint64_t>(elapsedNs.count()) >= uint64_t(timeout)) {
                    return kWaitSerialTimeout;
                }
                std::this_thread::yield();
            }
        }
    }

    // Completed queries will be recycled in CheckCompletedSerialsImpl();
    auto numCompletedQueries = sign_cast(std::distance(mPendingQueries.begin(), it) + 1);
    MarkPendingQueriesAsComplete(numCompletedQueries);
    return done ? waitSerial : kWaitSerialTimeout;
}

MaybeError DelayFlushQueue::BlockWaitForLastSubmittedSerial(
    const ScopedCommandRecordingContext* commandContext) {
    TRACE_EVENT0(GetDevice()->GetPlatform(), General,
                 "DelayFlushQueue::BlockWaitForLastSubmittedSerial");

    SystemEventReceiver receiver;
    DAWN_TRY_ASSIGN(receiver, GetSystemEventReceiver());
    commandContext->Flush1(D3D11_CONTEXT_TYPE_ALL, receiver.GetPrimitive().Get());

    DWORD result = WaitForSingleObject(receiver.GetPrimitive().Get(), INFINITE);
    DAWN_INTERNAL_ERROR_IF(result != WAIT_OBJECT_0, "WaitForSingleObject() failed");

    SystemEventReceiver returnedReceivers[] = {std::move(receiver)};
    return ReturnSystemEventReceivers(returnedReceivers);
}

void DelayFlushQueue::SetEventOnCompletion(ExecutionSerial serial, HANDLE event) {
    DAWN_UNREACHABLE();
}

void DelayFlushQueue::MarkPendingQueriesAsComplete(size_t numCompletedQueries) {
    mCompletedQueries.insert(
        mCompletedQueries.end(), std::make_move_iterator(mPendingQueries.begin()),
        std::make_move_iterator(mPendingQueries.begin() + sign_cast(numCompletedQueries)));

    mPendingQueries.erase(mPendingQueries.begin(),
                          mPendingQueries.begin() + sign_cast(numCompletedQueries));
}

ResultOrError<bool> DelayFlushQueue::IsQueryCompleted(
    const ScopedCommandRecordingContext* commandContext,
    bool requireFlush,
    EventQuery* eventQuery) {
    BOOL done;

    // If the GetData() calls count is 100 we will flush the commands. This is to avoid infinity
    // loop when the application uses device.Tick() in a busy wait. The number 100 is arbitrarily
    // chosen. It could be changed in future. Notes:
    // - We shouldn't trigger flush eagerly when calls count < 100 because the the flush might be
    // triggered externally via SwapChain's Present().
    // - We don't need to trigger flush when calls count > 100 because any commands preceding this
    // query should already be flushed when calls count is 100.
    // - If the caller requires a flush, we only trigger flush if the calls count < 100.
    // - TODO(416736350): Consider tracking last flush's serial so that we can skip the flush here
    // if necessary.
    constexpr size_t kFlushCheckpoint = 100;
    if (requireFlush && eventQuery->checkCount < kFlushCheckpoint) {
        eventQuery->checkCount = kFlushCheckpoint;
    }

    // Pass flag=0 if we want GetData() to flush the commands.
    const UINT dontFlushFlag =
        (eventQuery->checkCount == kFlushCheckpoint) ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH;
    HRESULT hr =
        commandContext->GetData(eventQuery->GetQuery(), &done, sizeof(done), dontFlushFlag);
    DAWN_TRY(CheckHRESULT(hr, "GetQueryData()"));

    eventQuery->checkCount++;

    // A return value of S_FALSE means the query is not completed.
    DAWN_ASSERT(hr == S_FALSE || done == TRUE);
    return hr == S_OK;
}

}  // namespace dawn::native::d3d11
