// 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/Queue.h"

#include <webgpu/webgpu.h>

#include <algorithm>
#include <cstring>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include "absl/cleanup/cleanup.h"
#include "dawn/native/ObjectType_autogen.h"
#include "dawn/platform/DawnPlatform.h"
#include "partition_alloc/pointers/raw_ptr.h"
#include "src/dawn/common/Constants.h"
#include "src/dawn/common/Enumerator.h"
#include "src/dawn/common/FutureUtils.h"
#include "src/dawn/common/StringViewUtils.h"
#include "src/dawn/common/ityp_span.h"
#include "src/dawn/native/BindGroup.h"
#include "src/dawn/native/BlitBufferToDepthStencil.h"
#include "src/dawn/native/Buffer.h"
#include "src/dawn/native/CommandBuffer.h"
#include "src/dawn/native/CommandEncoder.h"
#include "src/dawn/native/CommandValidation.h"
#include "src/dawn/native/Commands.h"
#include "src/dawn/native/CopyTextureForBrowserHelper.h"
#include "src/dawn/native/Device.h"
#include "src/dawn/native/DynamicUploader.h"
#include "src/dawn/native/EventManager.h"
#include "src/dawn/native/ExternalTexture.h"
#include "src/dawn/native/Instance.h"
#include "src/dawn/native/QuerySet.h"
#include "src/dawn/native/RenderPassEncoder.h"
#include "src/dawn/native/RenderPipeline.h"
#include "src/dawn/native/ResourceTable.h"
#include "src/dawn/native/Texture.h"
#include "src/dawn/platform/tracing/TraceEvent.h"
#include "src/utils/compiler.h"

namespace dawn::native {

namespace {

void CopyTextureData(uint8_t* dstPointer,
                     const uint8_t* srcPointer,
                     uint32_t depth,
                     uint32_t dstRowsPerImage,
                     uint64_t srcRowsPerImage,
                     uint32_t actualBytesPerRow,
                     uint32_t dstBytesPerRow,
                     uint32_t srcBytesPerRow) {
    uint64_t imageAdditionalStride = srcBytesPerRow * (srcRowsPerImage - dstRowsPerImage);
    bool copyWholeLayer = actualBytesPerRow == dstBytesPerRow && dstBytesPerRow == srcBytesPerRow;
    bool copyWholeData = copyWholeLayer && imageAdditionalStride == 0;

    if (!copyWholeLayer) {  // copy row by row
        for (uint32_t d = 0; d < depth; ++d) {
            for (uint32_t h = 0; h < dstRowsPerImage; ++h) {
                DAWN_UNSAFE_TODO(memcpy(dstPointer, srcPointer, actualBytesPerRow));
                DAWN_UNSAFE_TODO(dstPointer += dstBytesPerRow);
                DAWN_UNSAFE_TODO(srcPointer += srcBytesPerRow);
            }
            DAWN_UNSAFE_TODO(srcPointer += imageAdditionalStride);
        }
    } else {
        uint64_t layerSize = uint64_t(dstRowsPerImage) * actualBytesPerRow;
        if (!copyWholeData) {  // copy layer by layer
            for (uint32_t d = 0; d < depth; ++d) {
                DAWN_UNSAFE_TODO(memcpy(dstPointer, srcPointer, layerSize));
                DAWN_UNSAFE_TODO(dstPointer += layerSize);
                DAWN_UNSAFE_TODO(srcPointer += layerSize + imageAdditionalStride);
            }
        } else {  // do a single copy
            DAWN_UNSAFE_TODO(memcpy(dstPointer, srcPointer, layerSize * depth));
        }
    }
}

class ErrorQueue : public QueueBase {
  public:
    explicit ErrorQueue(DeviceBase* device, StringView label)
        : QueueBase(device, ObjectBase::kError, label) {}

  private:
    MaybeError SubmitImpl(uint32_t commandCount, CommandBufferBase* const* commands) override {
        DAWN_UNREACHABLE();
    }
    bool HasPendingCommands() const override { DAWN_UNREACHABLE(); }
    MaybeError SubmitPendingCommandsImpl() override { DAWN_UNREACHABLE(); }
    ResultOrError<ExecutionSerial> CheckAndUpdateCompletedSerials() override { DAWN_UNREACHABLE(); }
    void ForceEventualFlushOfCommands() override { DAWN_UNREACHABLE(); }
    ResultOrError<ExecutionSerial> WaitForQueueSerialImpl(ExecutionSerial waitSerial,
                                                          Nanoseconds timeout) override {
        DAWN_UNREACHABLE();
    }
    MaybeError WaitForIdleForDestructionImpl() override { DAWN_UNREACHABLE(); }
};

}  // namespace

// TrackTaskCallback

void TrackTaskCallback::SetFinishedSerial(ExecutionSerial serial) {
    mSerial = serial;
}

// QueueBase

QueueBase::QueueBase(DeviceBase* device, const QueueDescriptor* descriptor)
    : ExecutionQueueBase(device, descriptor->label) {
    GetObjectTrackingList()->Track(this);
}

QueueBase::QueueBase(DeviceBase* device, ObjectBase::ErrorTag tag, StringView label)
    : ExecutionQueueBase(device, tag, label) {}

QueueBase::~QueueBase() {
    DAWN_CHECK(mTasksInFlight->Empty());
}

void QueueBase::DestroyImpl(DestroyReason reason) {}

// static
Ref<QueueBase> QueueBase::MakeError(DeviceBase* device, StringView label) {
    return AcquireRef(new ErrorQueue(device, label));
}

ObjectType QueueBase::GetType() const {
    return ObjectType::Queue;
}

// It doesn't make much sense right now to mark the default queue as "unlabeled", so this override
// prevents that. Consider removing when multiqueue is implemented.
void QueueBase::FormatLabel(absl::FormatSink* s) const {
    s->Append(ObjectTypeAsString(GetType()));
    const std::string& label = GetLabel();
    if (!label.empty()) {
        s->Append(absl::StrFormat(" \"%s\"", label));
    }
}

void QueueBase::APISubmit(uint32_t commandCount, CommandBufferBase* const* commands) {
    MaybeError result = SubmitInternal(commandCount, commands);

    // Destroy the command buffers even if SubmitInternal failed. (crbug.com/dawn/1863)
    for (uint32_t i = 0; i < commandCount; ++i) {
        DAWN_UNSAFE_TODO(commands[i])->Destroy();
    }

    [[maybe_unused]] bool hadError = GetDevice()->ConsumedError(
        std::move(result), "calling %s.Submit(%s)", this,
        ityp::span<uint32_t, CommandBufferBase* const>(commands, commandCount));
}

Future QueueBase::APIOnSubmittedWorkDone(const WGPUQueueWorkDoneCallbackInfo& callbackInfo) {
    struct WorkDoneEvent final : public EventManager::TrackedEvent {
        std::optional<WGPUQueueWorkDoneStatus> mEarlyStatus;
        WGPUQueueWorkDoneCallback mCallback = nullptr;
        std::string mMessage = "";
        raw_ptr<void> mUserdata1 = nullptr;
        raw_ptr<void> mUserdata2 = nullptr;

        // Create an event backed by the given queue execution serial.
        WorkDoneEvent(const WGPUQueueWorkDoneCallbackInfo& callbackInfo,
                      QueueBase* queue,
                      ExecutionSerial serial)
            : TrackedEvent(static_cast<wgpu::CallbackMode>(callbackInfo.mode), queue, serial),
              mCallback(callbackInfo.callback),
              mUserdata1(callbackInfo.userdata1),
              mUserdata2(callbackInfo.userdata2) {}

        // Create an event that's ready at creation (for errors, etc.)
        WorkDoneEvent(const WGPUQueueWorkDoneCallbackInfo& callbackInfo,
                      QueueBase* queue,
                      wgpu::QueueWorkDoneStatus earlyStatus)
            : TrackedEvent(static_cast<wgpu::CallbackMode>(callbackInfo.mode),
                           queue,
                           queue->GetCompletedCommandSerial()),
              mEarlyStatus(ToAPI(earlyStatus)),
              mCallback(callbackInfo.callback),
              mUserdata1(callbackInfo.userdata1),
              mUserdata2(callbackInfo.userdata2) {}

        ~WorkDoneEvent() override { EnsureComplete(EventCompletionType::Shutdown); }

        void Complete(EventCompletionType completionType) override {
            // WorkDoneEvent has no error cases other than the mEarlyStatus ones.
            WGPUQueueWorkDoneStatus status = WGPUQueueWorkDoneStatus_Success;
            if (completionType == EventCompletionType::Shutdown) {
                status = WGPUQueueWorkDoneStatus_CallbackCancelled;
            } else if (mEarlyStatus) {
                status = mEarlyStatus.value();
            }

            mCallback(status, ToOutputStringView(mMessage), mUserdata1.ExtractAsDangling(),
                      mUserdata2.ExtractAsDangling());
        }
    };

    // TODO(crbug.com/dawn/2052): Once we always return a future, change this to log to the instance
    // (note, not raise a validation error to the device) and return the null future.
    DAWN_CHECK(callbackInfo.nextInChain == nullptr);

    Ref<EventManager::TrackedEvent> event;
    {
        // TODO(crbug.com/dawn/831) Manually acquire device lock instead of relying on code-gen for
        // re-entrancy.
        auto deviceGuard = GetDevice()->GetGuard();
        if (GetDevice()->ConsumedError(GetDevice()->ValidateIsAlive())) {
            event = AcquireRef(
                new WorkDoneEvent(callbackInfo, this, wgpu::QueueWorkDoneStatus::Success));
        } else if (GetDevice()->ConsumedError(ValidateOnSubmittedWorkDone())) {
            event =
                AcquireRef(new WorkDoneEvent(callbackInfo, this, wgpu::QueueWorkDoneStatus::Error));
        } else {
            event = AcquireRef(new WorkDoneEvent(callbackInfo, this, GetScheduledWorkDoneSerial()));
        }
    }

    // Note: if the callback is spontaneous, it may get called in here.
    FutureID futureID = GetInstance()->GetEventManager()->TrackEvent(std::move(event));

    return {futureID};
}

void QueueBase::TrackTask(std::unique_ptr<TrackTaskCallback> task, ExecutionSerial serial) {
    // If the task depends on a serial which is not submitted yet, force a flush.
    if (serial > GetLastSubmittedCommandSerial()) {
        ForceEventualFlushOfCommands();
    }

    DAWN_CHECK(serial <= GetScheduledWorkDoneSerial());

    // If the serial indicated command has been completed, the task will be moved to callback task
    // manager.
    if (serial <= GetCompletedCommandSerial()) {
        task->SetFinishedSerial(GetCompletedCommandSerial());
        GetDevice()->GetCallbackTaskManager()->AddCallbackTask(std::move(task));
    } else {
        mTasksInFlight->Enqueue(std::move(task), serial);
    }
}

void QueueBase::TrackTaskAfterEventualFlush(std::unique_ptr<TrackTaskCallback> task) {
    ForceEventualFlushOfCommands();
    TrackTask(std::move(task), GetScheduledWorkDoneSerial());
}

void QueueBase::TrackPendingTask(std::unique_ptr<TrackTaskCallback> task) {
    mTasksInFlight->Enqueue(std::move(task), GetPendingCommandSerial());
}

void QueueBase::Tick(ExecutionSerial finishedSerial) {
    // If a user calls Queue::Submit inside a task, for example in a Buffer::MapAsync callback,
    // then the device will be ticked, which in turns ticks the queue, causing reentrance here.
    // To prevent the reentrant call from invalidating mTasksInFlight while in use by the first
    // call, we remove the tasks to finish from the queue, update mTasksInFlight, then run the
    // callbacks.
    TRACE_EVENT1(GetDevice()->GetPlatform(), General, "Queue::Tick", "finishedSerial",
                 uint64_t(finishedSerial));

    std::vector<std::unique_ptr<TrackTaskCallback>> tasks;
    mTasksInFlight.Use([&](auto tasksInFlight) {
        for (auto& task : tasksInFlight->IterateUpTo(finishedSerial)) {
            tasks.push_back(std::move(task));
        }
        tasksInFlight->ClearUpTo(finishedSerial);
    });
    // Tasks' serials have passed. Move them to the callback task manager. They
    // are ready to be called.
    for (auto& task : tasks) {
        task->SetFinishedSerial(finishedSerial);
        GetDevice()->GetCallbackTaskManager()->AddCallbackTask(std::move(task));
    }
}

void QueueBase::HandleDeviceLoss() {
    mTasksInFlight.Use([&](auto tasksInFlight) {
        for (auto& task : tasksInFlight->IterateAll()) {
            task->OnDeviceLoss();
            GetDevice()->GetCallbackTaskManager()->AddCallbackTask(std::move(task));
        }
        tasksInFlight->Clear();
    });
}

void QueueBase::APIWriteBuffer(BufferBase* buffer,
                               uint64_t bufferOffset,
                               const void* data,
                               size_t size) {
    auto writeBuffer = [&]() -> MaybeError {
        DAWN_TRY(WriteBuffer(buffer, bufferOffset, data, size));
        return GetDevice()->GetDynamicUploader()->MaybeSubmitPendingCommands();
    };
    [[maybe_unused]] bool hadError = GetDevice()->ConsumedError(
        writeBuffer(), "calling %s.WriteBuffer(%s, (%d bytes), data, (%d bytes))", this, buffer,
        bufferOffset, size);
}

MaybeError QueueBase::WriteBuffer(BufferBase* buffer,
                                  uint64_t bufferOffset,
                                  const void* data,
                                  size_t size) {
    DAWN_TRY(GetDevice()->ValidateIsAlive());
    DAWN_TRY(GetDevice()->ValidateObject(this));
    DAWN_TRY(ValidateWriteBuffer(GetDevice(), buffer, bufferOffset, size));
    BufferBase::ScopedUseBuffer scopedUseBuffer;
    DAWN_TRY_ASSIGN(scopedUseBuffer, buffer->ValidateCanUseOnQueueNow());
    return WriteBufferImpl(buffer, bufferOffset, data, size);
}

MaybeError QueueBase::WriteBufferImpl(BufferBase* buffer,
                                      uint64_t bufferOffset,
                                      const void* data,
                                      size_t size) {
    return buffer->UploadData(bufferOffset, data, size);
}

void QueueBase::APIWriteTexture(const TexelCopyTextureInfo* destination,
                                const void* data,
                                size_t dataSize,
                                const TexelCopyBufferLayout* dataLayout,
                                const Extent3D* writeSize) {
    auto writeTexture = [&]() -> MaybeError {
        DAWN_TRY(WriteTextureInternal(destination, data, dataSize, *dataLayout, writeSize));
        return GetDevice()->GetDynamicUploader()->MaybeSubmitPendingCommands();
    };
    [[maybe_unused]] bool hadError = GetDevice()->ConsumedError(
        writeTexture(), "calling %s.WriteTexture(%s, (%u bytes), %s, %s)", this, destination,
        dataSize, dataLayout, writeSize);
}

MaybeError QueueBase::WriteTextureInternal(const TexelCopyTextureInfo* destinationOrig,
                                           const void* data,
                                           size_t dataSize,
                                           const TexelCopyBufferLayout& dataLayout,
                                           const Extent3D* writeSize) {
    TexelCopyTextureInfo destination = destinationOrig->WithTrivialFrontendDefaults();

    DAWN_TRY(ValidateWriteTexture(&destination, dataSize, dataLayout, writeSize));

    if (writeSize->width == 0 || writeSize->height == 0 || writeSize->depthOrArrayLayers == 0) {
        return {};
    }

    const TexelBlockInfo& blockInfo = GetBlockInfo(destination);
    TexelCopyBufferLayout layout = dataLayout;
    ApplyDefaultTexelCopyBufferLayoutOptions(&layout, blockInfo, *writeSize);
    return WriteTextureImpl(destination, data, dataSize, layout, *writeSize);
}

MaybeError QueueBase::WriteTextureImpl(const TexelCopyTextureInfo& destination,
                                       const void* data,
                                       size_t dataSize,
                                       const TexelCopyBufferLayout& dataLayout,
                                       const Extent3D& writeSizePixel) {
    const TypedTexelBlockInfo& blockInfo = GetBlockInfo(destination);
    BlockExtent3D writeSize = blockInfo.ToBlock(writeSizePixel);

    // We are only copying the part of the data that will appear in the texture.
    // Note that validating texture copy range ensures that writeSizePixel->width and
    // writeSizePixel->height are multiples of blockWidth and blockHeight respectively.
    BlockCount rowsPerImage = writeSize.height;
    uint32_t bytesPerRow = uint32_t(blockInfo.ToBytes(writeSize.width));
    uint32_t alignedBytesPerRow = Align(bytesPerRow, GetDevice()->GetOptimalBytesPerRowAlignment());
    BlockCount alignedBlocksPerRow = blockInfo.BytesToBlocks(alignedBytesPerRow);

    uint64_t packedDataSize =
        ComputeRequiredBytesInCopy(blockInfo, writeSize, alignedBlocksPerRow, rowsPerImage);

    // We need the offset to be aligned to both the optimal offset for that device and
    // blockByteSize, since both of them are powers of two, we only need to align to the max value.
    DAWN_CHECK(IsPowerOfTwo(GetDevice()->GetOptimalBufferToTextureCopyOffsetAlignment()));
    DAWN_CHECK(IsPowerOfTwo(blockInfo.byteSize));
    uint64_t offsetAlignment = std::max(
        uint64_t(blockInfo.byteSize), GetDevice()->GetOptimalBufferToTextureCopyOffsetAlignment());

    // Buffer offset alignments must follow additional restrictions for depth stencil formats.
    const Format& format = destination.texture->GetFormat();
    if (format.HasDepthOrStencil()) {
        offsetAlignment =
            std::max(offsetAlignment, GetDevice()->GetBufferCopyOffsetAlignmentForDepthStencil());
    }

    return GetDevice()->GetDynamicUploader()->WithUploadReservation(
        packedDataSize, offsetAlignment, [&](UploadReservation reservation) -> MaybeError {
            const uint8_t* srcPointer =
                DAWN_UNSAFE_TODO(reinterpret_cast<const uint8_t*>(data) + dataLayout.offset);
            uint8_t* dstPointer = reinterpret_cast<uint8_t*>(reservation.mappedPointer.get());
            CopyTextureData(dstPointer, srcPointer, writeSizePixel.depthOrArrayLayers,
                            dchecked_cast<uint32_t>(rowsPerImage), dataLayout.rowsPerImage,
                            bytesPerRow, alignedBytesPerRow, dataLayout.bytesPerRow);

            TexelCopyBufferLayout passDataLayout = dataLayout;
            passDataLayout.offset = reservation.offsetInBuffer;
            passDataLayout.bytesPerRow = alignedBytesPerRow;
            passDataLayout.rowsPerImage = dchecked_cast<uint32_t>(rowsPerImage);

            TextureCopy textureCopy;
            textureCopy.texture = destination.texture;
            textureCopy.mipLevel = destination.mipLevel;
            textureCopy.origin = destination.origin;
            textureCopy.aspect = ConvertAspect(format, destination.aspect);

            return GetDevice()->CopyFromStagingToTexture(reservation.buffer.Get(), passDataLayout,
                                                         textureCopy, writeSizePixel);
        });
}

void QueueBase::APICopyTextureForBrowser(const TexelCopyTextureInfo* source,
                                         const TexelCopyTextureInfo* destination,
                                         const Extent3D* copySize,
                                         const CopyTextureForBrowserOptions* options) {
    [[maybe_unused]] bool hadError = GetDevice()->ConsumedError(
        CopyTextureForBrowserInternal(source, destination, copySize, options));
}

void QueueBase::APICopyExternalTextureForBrowser(const ImageCopyExternalTexture* source,
                                                 const TexelCopyTextureInfo* destination,
                                                 const Extent3D* copySize,
                                                 const CopyTextureForBrowserOptions* options) {
    [[maybe_unused]] bool hadError = GetDevice()->ConsumedError(
        CopyExternalTextureForBrowserInternal(source, destination, copySize, options));
}

MaybeError QueueBase::CopyTextureForBrowserInternal(const TexelCopyTextureInfo* sourceOrig,
                                                    const TexelCopyTextureInfo* destinationOrig,
                                                    const Extent3D* copySize,
                                                    const CopyTextureForBrowserOptions* options) {
    TexelCopyTextureInfo source = sourceOrig->WithTrivialFrontendDefaults();
    TexelCopyTextureInfo destination = destinationOrig->WithTrivialFrontendDefaults();

    if (GetDevice()->IsValidationEnabled()) {
        DAWN_TRY_CONTEXT(
            ValidateCopyTextureForBrowser(GetDevice(), &source, &destination, copySize, options),
            "validating CopyTextureForBrowser from %s to %s", source.texture, destination.texture);
    }

    return DoCopyTextureForBrowser(GetDevice(), &source, &destination, copySize, options);
}

MaybeError QueueBase::CopyExternalTextureForBrowserInternal(
    const ImageCopyExternalTexture* source,
    const TexelCopyTextureInfo* destinationOrig,
    const Extent3D* copySize,
    const CopyTextureForBrowserOptions* options) {
    TexelCopyTextureInfo destination = destinationOrig->WithTrivialFrontendDefaults();

    if (GetDevice()->IsValidationEnabled()) {
        DAWN_TRY_CONTEXT(ValidateCopyExternalTextureForBrowser(GetDevice(), source, &destination,
                                                               copySize, options),
                         "validating CopyExternalTextureForBrowser from %s to %s",
                         source->externalTexture, destination.texture);
    }

    return DoCopyExternalTextureForBrowser(GetDevice(), source, &destination, copySize, options);
}

MaybeError QueueBase::ValidateSubmit(uint32_t commandCount,
                                     CommandBufferBase* const* commands,
                                     BufferSet& buffersFromCommands) const {
    TRACE_EVENT0(GetDevice()->GetPlatform(), Validation, "Queue::ValidateSubmit");
    DAWN_TRY(GetDevice()->ValidateObject(this));

    std::set<CommandBufferBase*> uniqueCommandBuffers;

    for (uint32_t i = 0; i < commandCount; ++i) {
        DAWN_UNSAFE_TODO(DAWN_TRY(GetDevice()->ValidateObject(commands[i])));
        DAWN_UNSAFE_TODO(DAWN_TRY(commands[i]->ValidateCanUseInSubmitNow()));

        auto insertResult = uniqueCommandBuffers.insert(DAWN_UNSAFE_TODO(commands[i]));
        DAWN_UNSAFE_TODO(DAWN_INVALID_IF(!insertResult.second, "Submit contains duplicates of %s.",
                                         commands[i]));

        const CommandBufferResourceUsage& usages =
            DAWN_UNSAFE_TODO(commands[i])->GetResourceUsages();

        auto ValidateBuffer = [&buffersFromCommands](BufferBase* buffer) -> MaybeError {
            if (auto [iter, inserted] = buffersFromCommands.insert(buffer); inserted) {
                BufferBase::ScopedUseBuffer use;
                DAWN_TRY_ASSIGN_WITH_CLEANUP(use, buffer->ValidateCanUseOnQueueNow(),
                                             { buffersFromCommands.erase(iter); });
                // FinishUse() will be called on the buffers in `buffersFromCommands` explicitly.
                use.Release();
            }
            return {};
        };

        // Maybe track last usage for other resources, and use it to release resources earlier?
        for (const SyncScopeResourceUsage& scope : usages.renderPasses) {
            for (BufferBase* buffer : scope.buffers) {
                DAWN_TRY(ValidateBuffer(buffer));
            }
            for (const TextureBase* texture : scope.textures) {
                DAWN_TRY(texture->ValidateCanUseInSubmitNow());
            }
            for (const ExternalTextureBase* externalTexture : scope.externalTextures) {
                DAWN_TRY(externalTexture->ValidateCanUseInSubmitNow());
            }
            for (const ResourceTableBase* resourceTable : scope.usedResourceTables) {
                DAWN_TRY(resourceTable->ValidateCanUseInSubmitNow());
            }
        }

        for (const ComputePassResourceUsage& pass : usages.computePasses) {
            for (BufferBase* buffer : pass.referencedBuffers) {
                DAWN_TRY(ValidateBuffer(buffer));
            }
            for (const TextureBase* texture : pass.referencedTextures) {
                DAWN_TRY(texture->ValidateCanUseInSubmitNow());
            }
            for (const ExternalTextureBase* externalTexture : pass.referencedExternalTextures) {
                DAWN_TRY(externalTexture->ValidateCanUseInSubmitNow());
            }
            for (const ResourceTableBase* resourceTable : pass.referencedResourceTables) {
                DAWN_TRY(resourceTable->ValidateCanUseInSubmitNow());
            }
        }

        for (BufferBase* buffer : usages.topLevelBuffers) {
            DAWN_TRY(ValidateBuffer(buffer));
        }
        for (const TextureBase* texture : usages.topLevelTextures) {
            DAWN_TRY(texture->ValidateCanUseInSubmitNow());
        }
        for (const QuerySetBase* querySet : usages.usedQuerySets) {
            DAWN_TRY(querySet->ValidateCanUseInSubmitNow());
        }

        // Validate that pinned textures are only used with their pinned usage. This is done in a
        // separate pass to avoid adding validation overhead to non-bindless while prototyping
        // bindless.
        // TODO(https://crbug.com/435317394): Merge this validation with the validation that
        // textures are not destroyed by turning the sets of resources in the PassUsageTracker into
        // maps of resources to usages, and doing a single bitmask check to know if there's an error
        // before finding out the reason why there is an error.
        if (GetDevice()->HasFeature(Feature::ChromiumExperimentalSamplingResourceTable)) {
            for (const TextureBase* texture : usages.topLevelTextures) {
                DAWN_INVALID_IF(texture->HasPinnedUsage(),
                                "%s is pinned to %s while used in a CommandEncoder command.",
                                texture, texture->GetPinnedUsage());
            }
            for (const SyncScopeResourceUsage& scope : usages.renderPasses) {
                for (auto [j, texture] : Enumerate(scope.textures)) {
                    if (!texture->HasPinnedUsage()) {
                        continue;
                    }

                    DAWN_TRY(scope.textureSyncInfos[j].Iterate(
                        [&](const SubresourceRange&, const TextureSyncInfo& info) -> MaybeError {
                            DAWN_INVALID_IF(info.usage != texture->GetPinnedUsage(),
                                            "%s is used as %s while pinned to %s.", texture,
                                            info.usage, texture->GetPinnedUsage());
                            return {};
                        }));
                }
            }
            for (const ComputePassResourceUsage& compute : usages.computePasses) {
                for (const SyncScopeResourceUsage& scope : compute.dispatchUsages) {
                    for (auto [j, texture] : Enumerate(scope.textures)) {
                        if (!texture->HasPinnedUsage()) {
                            continue;
                        }

                        DAWN_TRY(scope.textureSyncInfos[j].Iterate(
                            [&](const SubresourceRange&,
                                const TextureSyncInfo& info) -> MaybeError {
                                DAWN_INVALID_IF(info.usage != texture->GetPinnedUsage(),
                                                "%s is used as %s while pinned to %s.", texture,
                                                info.usage, texture->GetPinnedUsage());
                                return {};
                            }));
                    }
                }
            }
        }
    }

    return {};
}

MaybeError QueueBase::ValidateOnSubmittedWorkDone() const {
    DAWN_TRY(GetDevice()->ValidateObject(this));
    return {};
}

MaybeError QueueBase::ValidateWriteTexture(const TexelCopyTextureInfo* destination,
                                           size_t dataSize,
                                           const TexelCopyBufferLayout& dataLayout,
                                           const Extent3D* writeSize) const {
    DAWN_TRY(GetDevice()->ValidateIsAlive());
    DAWN_TRY(GetDevice()->ValidateObject(this));
    DAWN_TRY(GetDevice()->ValidateObject(destination->texture));

    DAWN_TRY(ValidateTexelCopyTextureInfo(GetDevice(), *destination, *writeSize));

    DAWN_INVALID_IF(dataLayout.offset > dataSize,
                    "Data offset (%u) is greater than the data size (%u).", dataLayout.offset,
                    dataSize);

    DAWN_INVALID_IF(!(destination->texture->GetUsage() & wgpu::TextureUsage::CopyDst),
                    "Usage (%s) of %s does not include %s.", destination->texture->GetUsage(),
                    destination->texture, wgpu::TextureUsage::CopyDst);
    DAWN_INVALID_IF(destination->texture->HasPinnedUsage(), "%s is pinned to %s.",
                    destination->texture, destination->texture->GetPinnedUsage());

    DAWN_INVALID_IF(destination->texture->GetSampleCount() > 1, "Sample count (%u) of %s is not 1",
                    destination->texture->GetSampleCount(), destination->texture);

    DAWN_TRY(ValidateLinearToDepthStencilCopyRestrictions(*destination));
    // We validate texture copy range before validating linear texture data,
    // because in the latter we divide copyExtent.width by blockWidth and
    // copyExtent.height by blockHeight while the divisibility conditions are
    // checked in validating texture copy range.
    DAWN_TRY(ValidateTextureCopyRange(GetDevice(), *destination, *writeSize));

    const TexelBlockInfo& blockInfo = GetBlockInfo(*destination);

    DAWN_TRY(ValidateLinearTextureData(dataLayout, dataSize, blockInfo, *writeSize));

    DAWN_TRY(destination->texture->ValidateCanUseInSubmitNow());

    return {};
}

MaybeError QueueBase::SubmitInternal(uint32_t commandCount, CommandBufferBase* const* commands) {
    DeviceBase* device = GetDevice();

    // If device is lost, don't let any commands be submitted
    DAWN_TRY(device->ValidateIsAlive());

    TRACE_EVENT0(device->GetPlatform(), General, "Queue::Submit");

    BufferSet buffersUsedInSubmit;
    absl::Cleanup finishUseBuffers = [&buffersUsedInSubmit]() {
        for (BufferBase* buffer : buffersUsedInSubmit) {
            buffer->FinishUse();
        }
    };
    if (device->IsValidationEnabled()) {
        // TODO(crbug.com/425472913): Keep a rolling average of set size so this can reserve a
        // sufficiently large set for max of last N submits.
        DAWN_TRY(ValidateSubmit(commandCount, commands, buffersUsedInSubmit));
    }
    DAWN_CHECK(!IsError());

    DAWN_TRY(SubmitImpl(commandCount, commands));

    // Switch the buffer state back to unmapped before Tick().
    std::move(finishUseBuffers).Invoke();

    // Call Tick() to flush pending work.
    DAWN_TRY(device->Tick());

    return {};
}

}  // namespace dawn::native
