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

#include <string_view>
#include <utility>
#include <vector>

#include "absl/container/inlined_vector.h"
#include "dawn/native/ObjectType_autogen.h"
#include "dawn/native/ValidationUtils_autogen.h"
#include "dawn/platform/DawnPlatform.h"
#include "partition_alloc/pointers/raw_ptr.h"
#include "src/dawn/common/Enumerator.h"
#include "src/dawn/common/Math.h"
#include "src/dawn/native/Adapter.h"
#include "src/dawn/native/ApplyClearColorValueWithDrawHelper.h"
#include "src/dawn/native/BindGroup.h"
#include "src/dawn/native/BlitBufferToDepthStencil.h"
#include "src/dawn/native/BlitBufferToTexture.h"
#include "src/dawn/native/BlitDepthToDepth.h"
#include "src/dawn/native/BlitTextureToBuffer.h"
#include "src/dawn/native/Buffer.h"
#include "src/dawn/native/ChainUtils.h"
#include "src/dawn/native/CommandBuffer.h"
#include "src/dawn/native/CommandBufferStateTracker.h"
#include "src/dawn/native/CommandValidation.h"
#include "src/dawn/native/Commands.h"
#include "src/dawn/native/ComputePassEncoder.h"
#include "src/dawn/native/Device.h"
#include "src/dawn/native/ErrorData.h"
#include "src/dawn/native/QueryHelper.h"
#include "src/dawn/native/QuerySet.h"
#include "src/dawn/native/Queue.h"
#include "src/dawn/native/RenderPassEncoder.h"
#include "src/dawn/native/RenderPassWorkaroundsHelper.h"
#include "src/dawn/native/RenderPipeline.h"
#include "src/dawn/native/ValidationUtils.h"
#include "src/dawn/native/dawn_platform.h"
#include "src/dawn/native/utils/WGPUHelpers.h"
#include "src/dawn/platform/tracing/TraceEvent.h"
#include "src/utils/compiler.h"
#include "src/utils/non_movable.h"
#include "src/utils/span.h"

namespace dawn::native {

namespace {

// Record the subresource range of a attachment used in render pass for checking overlaps.
struct RecordedAttachment {
    raw_ptr<const TextureBase> texture = nullptr;
    uint32_t mipLevel = 0;
    // For 3d color attachment, it's the attachment's depthSlice.
    uint32_t depthOrArrayLayer = 0;

    bool operator==(const RecordedAttachment& other) const = default;
};

enum class AttachmentType : uint8_t {
    ColorAttachment,
    ResolveTarget,
    DepthStencilAttachment,
    StorageAttachment
};

std::string_view GetAttachmentTypeStr(AttachmentType type) {
    switch (type) {
        case AttachmentType::ColorAttachment:
            return "color attachment";
        case AttachmentType::ResolveTarget:
            return "resolve target";
        case AttachmentType::DepthStencilAttachment:
            return "depth stencil attachment";
        case AttachmentType::StorageAttachment:
            return "storage attachment";
    }
    DAWN_UNREACHABLE();
}

// The width, height, sample count and subresource range need to be validated between all
// attachments in the render pass. This class records all the states and validate them for each
// attachment.
class RenderPassValidationState final : public NonMovable {
  public:
    // Record the attachment in the render pass if it passes all validations:
    // - the attachment has same with, height and sample count with other attachments
    // - no overlaps with other attachments
    // TODO(dawn:1020): Improve the error messages to include the index information of the
    // attachment in the render pass descriptor.
    MaybeError AddAttachment(const TextureViewBase* attachment,
                             AttachmentType attachmentType,
                             uint32_t depthSlice = wgpu::kDepthSliceUndefined) {
        if (attachment == nullptr) {
            return {};
        }

        DAWN_CHECK(attachment->GetLevelCount() == 1);

        const std::string_view attachmentTypeStr = GetAttachmentTypeStr(attachmentType);

        // Validate attachment sample count.
        if (mMsrtssAllowed) {
            switch (attachmentType) {
                case AttachmentType::ColorAttachment:
                    // Color attachments must match either the implicit sample count or 1
                    DAWN_INVALID_IF(
                        attachment->GetTexture()->GetSampleCount() != 1 &&
                            attachment->GetTexture()->GetSampleCount() != mSampleCount,
                        "The %s %s sample count (%u) is not 1 or %u when the render pass "
                        "has an explicit sample count (%u).",
                        attachmentTypeStr, attachment, attachment->GetTexture()->GetSampleCount(),
                        mSampleCount, mSampleCount);
                    break;
                case AttachmentType::DepthStencilAttachment:
                    // Depth/stencil attachments must match the implicit sample count
                    DAWN_INVALID_IF(attachment->GetTexture()->GetSampleCount() != mSampleCount,
                                    "The %s %s sample count (%u) does not match the render pass "
                                    "explicit sample count (%u).",
                                    attachmentTypeStr, attachment,
                                    attachment->GetTexture()->GetSampleCount(), mSampleCount);
                    break;
                case AttachmentType::ResolveTarget:
                    // Resolve target sample counts are already validated to be 1 elsewhere.
                    break;
                case AttachmentType::StorageAttachment:
                    // PLS is not currently compatible with MSRTSS.
                    DAWN_UNREACHABLE();
            }
        } else if (HasAttachment()) {
            // If no explicit sample count is set, all attachment sample counts must match.
            DAWN_INVALID_IF(attachmentType != AttachmentType::ResolveTarget &&
                                attachment->GetTexture()->GetSampleCount() != mSampleCount,
                            "The %s %s sample count (%u) does not match the sample count of the "
                            "other attachments (%u).",
                            attachmentTypeStr, attachment,
                            attachment->GetTexture()->GetSampleCount(), mSampleCount);
        }

        Extent3D renderSize = attachment->GetSingleSubresourceVirtualSize();
        Extent3D attachmentValidationSize = renderSize;
        if (attachment->GetTexture()->GetFormat().IsMultiPlanar()) {
            // For multi-planar texture, D3D requires depth stencil buffer size must be equal to the
            // size of the plane 0 for the color attachment texture (`attachmentValidationSize`).
            // Vulkan, Metal and GL requires buffer size equal or bigger than render size. To make
            // all dawn backends work, dawn requires depth attachment's size equal to the
            // `attachmentValidationSize`.
            // Vulkan:
            // https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkFramebufferCreateInfo.html#VUID-VkFramebufferCreateInfo-flags-04533
            // OpenGLES3.0 (https://www.khronos.org/registry/OpenGL/specs/es/3.0/es_spec_3.0.pdf
            // section 4.4.4.2) allows attachments have unequal size.
            attachmentValidationSize =
                attachment->GetTexture()->GetMipLevelSingleSubresourceVirtualSize(
                    attachment->GetBaseMipLevel(), Aspect::Plane0);
        }

        if (mExpandResolveRect) {
            if (attachmentType == AttachmentType::ColorAttachment) {
                DAWN_INVALID_IF(
                    static_cast<uint64_t>(mExpandResolveRect->colorOffsetX) +
                            static_cast<uint64_t>(mExpandResolveRect->width) >
                        renderSize.width,
                    "The color's x (%u) and width (%u) of ExpandResolveRect is out of the render "
                    "area width(%u).",
                    mExpandResolveRect->colorOffsetX, mExpandResolveRect->width, renderSize.width);
                DAWN_INVALID_IF(static_cast<uint64_t>(mExpandResolveRect->colorOffsetY) +
                                        static_cast<uint64_t>(mExpandResolveRect->height) >
                                    renderSize.height,
                                "The color's y (%u) and height (%u) of ExpandResolveRect is out of "
                                "the render area "
                                "height(%u).",
                                mExpandResolveRect->colorOffsetY, mExpandResolveRect->height,
                                renderSize.height);
            } else if (attachmentType == AttachmentType::ResolveTarget) {
                DAWN_INVALID_IF(static_cast<uint64_t>(mExpandResolveRect->resolveOffsetX) +
                                        static_cast<uint64_t>(mExpandResolveRect->width) >
                                    renderSize.width,
                                "The resolve's x (%u) and width (%u) of ExpandResolveRect is out "
                                "of the resolve "
                                "area width(%u).",
                                mExpandResolveRect->resolveOffsetX, mExpandResolveRect->width,
                                renderSize.width);
                DAWN_INVALID_IF(static_cast<uint64_t>(mExpandResolveRect->resolveOffsetY) +
                                        static_cast<uint64_t>(mExpandResolveRect->height) >
                                    renderSize.height,
                                "The resolve's y (%u) and height (%u) of ExpandResolveRect is out "
                                "of the resolve area "
                                "height(%u).",
                                mExpandResolveRect->resolveOffsetY, mExpandResolveRect->height,
                                renderSize.height);
            }
        }
        if (HasAttachment()) {
            switch (attachmentType) {
                case AttachmentType::ColorAttachment:
                case AttachmentType::StorageAttachment: {
                    DAWN_INVALID_IF(
                        renderSize.width != mRenderWidth || renderSize.height != mRenderHeight,
                        "The %s %s size (width: %u, height: %u) does not match the size of the "
                        "other attachments (width: %u, height: %u).",
                        attachmentTypeStr, attachment, renderSize.width, renderSize.height,
                        mRenderWidth, mRenderHeight);
                    break;
                }
                case AttachmentType::ResolveTarget: {
                    // TODO(chromium:324422644): support using multi-planar texture as resolve
                    // target.
                    DAWN_INVALID_IF(attachment->GetTexture()->GetFormat().IsMultiPlanar(),
                                    "The resolve target %s used as resolve target is from a "
                                    "multi-planar texture. It is not supported by dawn yet.",
                                    attachment);
                    // RenderPassDescriptorResolveRect relaxes the requirement for the color
                    // attachment texture size to match the resolve texture size.
                    if (!mExpandResolveRect) {
                        DAWN_INVALID_IF(
                            renderSize.width != mRenderWidth || renderSize.height != mRenderHeight,
                            "The resolve target %s size (width: %u, height: %u) does not match the "
                            "size of the other attachments (width: %u, height: %u).",
                            attachment, renderSize.width, renderSize.height, mRenderWidth,
                            mRenderHeight);
                    }
                    break;
                }
                case AttachmentType::DepthStencilAttachment: {
                    DAWN_INVALID_IF(
                        attachmentValidationSize.width != mAttachmentValidationWidth ||
                            attachmentValidationSize.height != mAttachmentValidationHeight,
                        "The depth stencil attachment %s size (width: %u, height: %u) does not "
                        "match the size of the other attachments' base plane (width: %u, height: "
                        "%u).",
                        attachment, attachmentValidationSize.width, attachmentValidationSize.height,
                        mAttachmentValidationWidth, mAttachmentValidationHeight);
                    break;
                }
            }
        } else {
            DAWN_CHECK(attachmentType != AttachmentType::ResolveTarget);
            mRenderWidth = renderSize.width;
            mRenderHeight = renderSize.height;
            mAttachmentValidationWidth = attachmentValidationSize.width;
            mAttachmentValidationHeight = attachmentValidationSize.height;
            if (!mMsrtssAllowed) {
                mSampleCount = attachment->GetTexture()->GetSampleCount();
            }
            DAWN_CHECK(mRenderWidth != 0);
            DAWN_CHECK(mRenderHeight != 0);
            DAWN_CHECK(mAttachmentValidationWidth != 0);
            DAWN_CHECK(mAttachmentValidationHeight != 0);
            DAWN_CHECK(mSampleCount != 0);
        }

        RecordedAttachment record;
        record.texture = attachment->GetTexture();
        record.mipLevel = attachment->GetBaseMipLevel();
        if (attachment->GetDimension() == wgpu::TextureViewDimension::e3D) {
            DAWN_CHECK(attachment->GetBaseArrayLayer() == 0);
            record.depthOrArrayLayer = depthSlice;
        } else {
            DAWN_CHECK(depthSlice == wgpu::kDepthSliceUndefined);
            record.depthOrArrayLayer = attachment->GetBaseArrayLayer();
        }

        for (size_t i = 0; i < mRecords.size(); i++) {
            DAWN_INVALID_IF(
                mRecords[i] == record,
                "The %s %s has read-write or write-write conflict with another attachment.",
                attachmentTypeStr, attachment);
        }

        mRecords.push_back(record);

        return {};
    }

    // Only sets the values needed for executing the render pass, used when validation is disabled.
    void SetUnvalidatedAttachment(const TextureViewBase* attachment) {
        // Should only be called once.
        DAWN_CHECK(!HasAttachment());

        DAWN_CHECK(attachment);
        DAWN_CHECK(attachment->GetLevelCount() == 1);

        Extent3D renderSize = attachment->GetSingleSubresourceVirtualSize();
        mRenderWidth = renderSize.width;
        mRenderHeight = renderSize.height;
        mAttachmentValidationWidth = mRenderWidth;
        mAttachmentValidationHeight = mRenderHeight;
        if (!mMsrtssAllowed) {
            mSampleCount = attachment->GetTexture()->GetSampleCount();
        }

        DAWN_CHECK(mRenderWidth != 0);
        DAWN_CHECK(mRenderHeight != 0);
        DAWN_CHECK(mSampleCount != 0);

        RecordedAttachment record;
        record.texture = attachment->GetTexture();
        record.mipLevel = attachment->GetBaseMipLevel();
        mRecords.push_back(record);
    }

    bool HasAttachment() const { return !mRecords.empty(); }

    bool IsValidState() const {
        return ((mRenderWidth > 0) && (mRenderHeight > 0) && (mSampleCount > 0));
    }

    uint32_t GetRenderWidth() const { return mRenderWidth; }

    uint32_t GetRenderHeight() const { return mRenderHeight; }

    uint32_t GetSampleCount() const { return mSampleCount; }

    uint32_t IsMsrtssAllowed() const { return mMsrtssAllowed; }

    void SetExplicitSampleCount(uint32_t sampleCount) {
        mSampleCount = sampleCount;
        mMsrtssAllowed = true;
    }

    bool WillExpandResolveTexture() const { return mWillExpandResolveTexture; }
    void SetWillExpandResolveTexture(bool enabled) { mWillExpandResolveTexture = enabled; }
    void SetExpandResolveRect(
        const std::optional<RenderPassDescriptorResolveRect>& expandResolveRect) {
        mExpandResolveRect = expandResolveRect;
    }

  private:
    // The attachment's width, height and sample count.
    uint32_t mRenderWidth = 0;
    uint32_t mRenderHeight = 0;
    uint32_t mSampleCount = 0;
    bool mMsrtssAllowed = false;

    uint32_t mAttachmentValidationWidth = 0;
    uint32_t mAttachmentValidationHeight = 0;

    // The records of the attachments that were validated in render pass.
    absl::InlinedVector<RecordedAttachment, kMaxColorAttachments> mRecords;

    bool mWillExpandResolveTexture = false;
    std::optional<RenderPassDescriptorResolveRect> mExpandResolveRect;
};

MaybeError ValidateB2BCopyAlignment(uint64_t dataSize, uint64_t srcOffset, uint64_t dstOffset) {
    // Copy size must be a multiple of 4 bytes on macOS.
    DAWN_INVALID_IF(dataSize % 4 != 0, "Copy size (%u) is not a multiple of 4.", dataSize);

    // SourceOffset and destinationOffset must be multiples of 4 bytes on macOS.
    DAWN_INVALID_IF(srcOffset % 4 != 0 || dstOffset % 4 != 0,
                    "Source offset (%u) or destination offset (%u) is not a multiple of 4 bytes,",
                    srcOffset, dstOffset);

    return {};
}

MaybeError ValidateTextureSampleCountInBufferCopyCommands(const TextureBase* texture) {
    DAWN_INVALID_IF(texture->GetSampleCount() > 1,
                    "%s sample count (%u) is not 1 when copying to or from a buffer.", texture,
                    texture->GetSampleCount());

    return {};
}

MaybeError ValidateLinearTextureCopyOffset(const TexelCopyBufferLayout& layout,
                                           const TexelBlockInfo& blockInfo,
                                           const bool hasDepthOrStencil) {
    if (hasDepthOrStencil) {
        // For depth-stencil texture, buffer offset must be a multiple of 4.
        DAWN_INVALID_IF(layout.offset % 4 != 0,
                        "Offset (%u) is not a multiple of 4 for depth/stencil texture.",
                        layout.offset);
    } else {
        DAWN_INVALID_IF(layout.offset % blockInfo.byteSize != 0,
                        "Offset (%u) is not a multiple of the texel block byte size (%u).",
                        layout.offset, blockInfo.byteSize);
    }
    return {};
}

MaybeError ValidateTextureFormatForTextureToBufferCopyInCompatibilityMode(
    const TextureBase* texture) {
    DAWN_INVALID_IF(texture->GetFormat().isCompressed,
                    "%s with format %s cannot be used as the source in a texture to buffer copy in "
                    "compatibility mode.",
                    texture, texture->GetFormat().format);
    return {};
}

MaybeError ValidateSourceTextureFormatForTextureToTextureCopyInCompatibilityMode(
    const TextureBase* texture) {
    DAWN_INVALID_IF(
        texture->GetFormat().isCompressed,
        "%s with format %s cannot be used as the source in a texture to texture copy in "
        "compatibility mode.",
        texture, texture->GetFormat().format);
    return {};
}

MaybeError ValidateTextureDepthStencilToBufferCopyRestrictions(const DeviceBase* device,
                                                               const TexelCopyTextureInfo& src) {
    Aspect aspectUsed;
    DAWN_TRY_ASSIGN(aspectUsed, SingleAspectUsedByTexelCopyTextureInfo(src));
    if (aspectUsed == Aspect::Depth) {
        switch (src.texture->GetFormat().format) {
            case wgpu::TextureFormat::Depth24Plus:
            case wgpu::TextureFormat::Depth24PlusStencil8:
                if (!device->IsToggleEnabled(Toggle::UseBlitForDepth24PlusTextureToBufferCopy)) {
                    return DAWN_VALIDATION_ERROR(
                        "The depth aspect of %s format %s cannot be selected in a texture to "
                        "buffer copy.",
                        src.texture, src.texture->GetFormat().format);
                }
                break;
            case wgpu::TextureFormat::Depth32Float:
            case wgpu::TextureFormat::Depth16Unorm:
            case wgpu::TextureFormat::Depth32FloatStencil8:
                break;

            default:
                DAWN_UNREACHABLE();
        }
    }

    return {};
}

MaybeError ValidateAttachmentArrayLayersAndLevelCount(const TextureViewBase* attachment) {
    // Currently we do not support layered rendering.
    DAWN_INVALID_IF(attachment->GetLayerCount() > 1,
                    "The layer count (%u) of %s used as attachment is greater than 1.",
                    attachment->GetLayerCount(), attachment);

    DAWN_INVALID_IF(attachment->GetLevelCount() > 1,
                    "The mip level count (%u) of %s used as attachment is greater than 1.",
                    attachment->GetLevelCount(), attachment);

    return {};
}

MaybeError ValidateResolveTarget(const DeviceBase* device,
                                 const RenderPassColorAttachment& colorAttachment,
                                 UsageValidationMode usageValidationMode) {
    if (colorAttachment.resolveTarget == nullptr) {
        return {};
    }

    const TextureViewBase* resolveTarget = colorAttachment.resolveTarget;
    const TextureViewBase* attachment = colorAttachment.view;
    DAWN_TRY(device->ValidateObject(resolveTarget));
    DAWN_TRY(
        ValidateCanUseAs(resolveTarget, wgpu::TextureUsage::RenderAttachment, usageValidationMode));
    DAWN_INVALID_IF(resolveTarget->GetUsage() & wgpu::TextureUsage::TransientAttachment,
                    "Cannot use transient attachment %s as a resolve target.", resolveTarget);

    DAWN_INVALID_IF(!attachment->GetTexture()->IsMultisampledTexture(),
                    "Cannot set %s as a resolve target when the color attachment %s has a sample "
                    "count of 1.",
                    resolveTarget, attachment);

    DAWN_INVALID_IF(resolveTarget->GetTexture()->IsMultisampledTexture(),
                    "Cannot use %s as resolve target. Sample count (%u) is greater than 1.",
                    resolveTarget, resolveTarget->GetTexture()->GetSampleCount());

    DAWN_INVALID_IF(resolveTarget->GetDimension() != wgpu::TextureViewDimension::e2D &&
                        resolveTarget->GetDimension() != wgpu::TextureViewDimension::e2DArray,
                    "The dimension (%s) of resolve target %s is not 2D or 2DArray.",
                    resolveTarget->GetDimension(), resolveTarget);

    DAWN_INVALID_IF(resolveTarget->GetLayerCount() > 1,
                    "The resolve target %s array layer count (%u) is not 1.", resolveTarget,
                    resolveTarget->GetLayerCount());

    DAWN_INVALID_IF(resolveTarget->GetLevelCount() > 1,
                    "The resolve target %s mip level count (%u) is not 1.", resolveTarget,
                    resolveTarget->GetLevelCount());

    wgpu::TextureFormat resolveTargetFormat = resolveTarget->GetFormat().format;
    DAWN_INVALID_IF(
        resolveTargetFormat != attachment->GetFormat().format,
        "The resolve target %s format (%s) does not match the color attachment %s format "
        "(%s).",
        resolveTarget, resolveTargetFormat, attachment, attachment->GetFormat().format);
    DAWN_INVALID_IF(
        !resolveTarget->GetFormat().SupportsResolveTarget(),
        "The resolve target %s format (%s) does not support being used as resolve target.",
        resolveTarget, resolveTargetFormat);

    // TODO(450506641): Precompute allowed usages of texture views (including swizzle identity
    // check) instead of recomputing.
    DAWN_INVALID_IF(!resolveTarget->IsSwizzleIdentity(),
                    "The resolve target swizzle must be identity.");

    return {};
}

MaybeError ValidateColorAttachmentDepthSlice(const TextureViewBase* attachment,
                                             uint32_t depthSlice) {
    if (attachment->GetDimension() != wgpu::TextureViewDimension::e3D) {
        DAWN_INVALID_IF(depthSlice != wgpu::kDepthSliceUndefined,
                        "depthSlice (%u) is defined for a non-3D attachment (%s).", depthSlice,
                        attachment);
        return {};
    }

    DAWN_INVALID_IF(depthSlice == wgpu::kDepthSliceUndefined,
                    "depthSlice is required for a 3D attachment (%s), but it is undefined.",
                    attachment);

    const Extent3D& attachmentSize = attachment->GetSingleSubresourceVirtualSize();
    DAWN_INVALID_IF(depthSlice >= attachmentSize.depthOrArrayLayers,
                    "depthSlice (%u) of the attachment (%s) is >= the "
                    "depthOrArrayLayers (%u) of the attachment's subresource at mip level (%u).",
                    depthSlice, attachment, attachmentSize.depthOrArrayLayers,
                    attachment->GetBaseMipLevel());

    return {};
}

MaybeError ValidateDawnRenderPassSampleCount(
    const DeviceBase* device,
    const DawnRenderPassSampleCount* renderPassSampleCount) {
    DAWN_ASSERT(renderPassSampleCount != nullptr);

    DAWN_INVALID_IF(
        !device->HasFeature(Feature::MSAARenderToSingleSampled),
        "The render pass has an explicit sample count while the %s feature is not enabled.",
        ToAPI(Feature::MSAARenderToSingleSampled));

    DAWN_INVALID_IF(!IsValidSampleCount(renderPassSampleCount->sampleCount) ||
                        renderPassSampleCount->sampleCount <= 1,
                    "The render pass sample count (%u) is not supported.",
                    renderPassSampleCount->sampleCount);

    return {};
}

MaybeError ValidateColorAttachmentRenderToSingleSampled(
    const DeviceBase* device,
    const RenderPassColorAttachment& colorAttachment,
    const DawnRenderPassSampleCount* renderPassSampleCount) {
    TextureViewBase* attachment = colorAttachment.view;
    DAWN_CHECK(attachment);

    DAWN_ASSERT(renderPassSampleCount != nullptr);
    DAWN_CHECK(device->HasFeature(Feature::MSAARenderToSingleSampled));

    uint32_t passSampleCount = renderPassSampleCount->sampleCount;
    uint32_t attachmentSampleCount = attachment->GetTexture()->GetSampleCount();
    DAWN_INVALID_IF(attachmentSampleCount != 1 && attachmentSampleCount != passSampleCount,
                    "The color attachment %s sample count (%u) must be either 1 or %u when the "
                    "render pass is using MSAARenderToSingleSampled with a sample count of %u.",
                    attachment, attachmentSampleCount, passSampleCount, passSampleCount);

    if (attachmentSampleCount != 1) {
        // The following rules only apply to attachments that will actually be resolved.
        return {};
    }

    DAWN_INVALID_IF(!attachment->GetFormat().SupportsResolveTarget(),
                    "The color attachment %s format (%s) does not support being used with a render "
                    "pass using MSAARenderToSingleSampled with a sample count of %u. The format "
                    "does not support resolve.",
                    attachment, attachment->GetFormat().format, passSampleCount);

    DAWN_INVALID_IF(colorAttachment.resolveTarget != nullptr,
                    "Cannot set %s as a resolve target. No resolve target should be specified "
                    "for the color attachment %s when the render pass is using "
                    "MSAARenderToSingleSampled with a sample count of %u.",
                    colorAttachment.resolveTarget, attachment, passSampleCount);

    return {};
}

MaybeError ValidateExpandResolveTextureLoadOp(const DeviceBase* device,
                                              const RenderPassColorAttachment& colorAttachment,
                                              RenderPassValidationState* validationState) {
    DAWN_INVALID_IF(!device->HasFeature(Feature::DawnLoadResolveTexture),
                    "%s is used while the %s is not enabled.", wgpu::LoadOp::ExpandResolveTexture,
                    ToAPI(Feature::DawnLoadResolveTexture));

    uint32_t textureSampleCount = colorAttachment.view->GetTexture()->GetSampleCount();

    DAWN_INVALID_IF(!IsValidSampleCount(textureSampleCount) || textureSampleCount <= 1,
                    "The color attachment %s's sample count (%u) is not supported by %s.",
                    colorAttachment.view, textureSampleCount, wgpu::LoadOp::ExpandResolveTexture);

    // These should already be validated before entering this function.
    DAWN_CHECK(colorAttachment.resolveTarget != nullptr &&
               !colorAttachment.resolveTarget->IsError());
    DAWN_CHECK(colorAttachment.view->GetFormat().SupportsResolveTarget());

    DAWN_INVALID_IF(
        (colorAttachment.resolveTarget->GetUsage() & wgpu::TextureUsage::TextureBinding) == 0,
        "Resolve target %s was not created with %s usage, which is required for "
        "%s.",
        colorAttachment.resolveTarget, wgpu::TextureUsage::TextureBinding,
        wgpu::LoadOp::ExpandResolveTexture);

    // TODO(42240662): multiplanar textures are not supported as resolve target.
    // The RenderPassValidationState currently rejects such usage.
    DAWN_CHECK(!colorAttachment.resolveTarget->GetTexture()->GetFormat().IsMultiPlanar());

    validationState->SetWillExpandResolveTexture(true);

    return {};
}

MaybeError ValidateRenderPassColorAttachment(DeviceBase* device,
                                             const RenderPassColorAttachment& colorAttachment,
                                             UsageValidationMode usageValidationMode,
                                             RenderPassValidationState* validationState) {
    TextureViewBase* attachment = colorAttachment.view;
    if (attachment == nullptr) {
        return {};
    }

    DAWN_TRY(device->ValidateObject(attachment));
    DAWN_TRY(
        ValidateCanUseAs(attachment, wgpu::TextureUsage::RenderAttachment, usageValidationMode));

    UnpackedPtr<RenderPassColorAttachment> unpacked;
    DAWN_TRY_ASSIGN(unpacked, ValidateAndUnpack(&colorAttachment));

    // Plane0, Plane1, and Plane2 aspects for multiplanar texture views should be allowed as color
    // attachments.
    Aspect kRenderableAspects = Aspect::Color | Aspect::Plane0 | Aspect::Plane1 | Aspect::Plane2;
    DAWN_INVALID_IF(
        !(attachment->GetAspects() & kRenderableAspects) || !attachment->GetFormat().IsRenderable(),
        "The color attachment %s format (%s) is not color renderable.", attachment,
        attachment->GetFormat().format);

    DAWN_TRY(ValidateLoadOp(colorAttachment.loadOp));
    DAWN_TRY(ValidateStoreOp(colorAttachment.storeOp));
    DAWN_INVALID_IF(colorAttachment.loadOp == wgpu::LoadOp::Undefined, "loadOp must be set.");
    DAWN_INVALID_IF(colorAttachment.storeOp == wgpu::StoreOp::Undefined, "storeOp must be set.");

    // TODO(450506641): Precompute allowed usages of texture views (including swizzle identity
    // check) instead of recomputing.
    DAWN_INVALID_IF(!attachment->IsSwizzleIdentity(),
                    "The color attachment swizzle must be identity.");

    if (attachment->GetUsage() & wgpu::TextureUsage::TransientAttachment) {
        DAWN_INVALID_IF(colorAttachment.loadOp != wgpu::LoadOp::Clear &&
                            colorAttachment.loadOp != wgpu::LoadOp::ExpandResolveTexture,
                        "The color attachment %s has the load op set to %s while its usage (%s) "
                        "has the transient attachment bit set.",
                        attachment, colorAttachment.loadOp, attachment->GetUsage());
        DAWN_INVALID_IF(colorAttachment.storeOp != wgpu::StoreOp::Discard,
                        "The color attachment %s has the store op set to %s while its usage (%s) "
                        "has the transient attachment bit set.",
                        attachment, wgpu::StoreOp::Store, attachment->GetUsage());
    }

    const dawn::native::Color& clearValue = colorAttachment.clearValue;
    if (colorAttachment.loadOp == wgpu::LoadOp::Clear) {
        DAWN_TRY(ValidateColor("clearValue", clearValue));
    } else if (colorAttachment.loadOp == wgpu::LoadOp::ExpandResolveTexture) {
        DAWN_INVALID_IF(colorAttachment.resolveTarget == nullptr,
                        "%s is used without resolve target.", wgpu::LoadOp::ExpandResolveTexture);
    }

    DAWN_TRY(ValidateColorAttachmentDepthSlice(attachment, colorAttachment.depthSlice));
    DAWN_TRY(ValidateAttachmentArrayLayersAndLevelCount(attachment));

    DAWN_TRY(validationState->AddAttachment(attachment, AttachmentType::ColorAttachment,
                                            colorAttachment.depthSlice));

    DAWN_TRY(ValidateResolveTarget(device, colorAttachment, usageValidationMode));

    if (colorAttachment.loadOp == wgpu::LoadOp::ExpandResolveTexture) {
        DAWN_TRY(ValidateExpandResolveTextureLoadOp(device, colorAttachment, validationState));
    }
    // Add resolve target after adding color attachment to make sure there is already a color
    // attachment for the comparison of width and height.
    DAWN_TRY(validationState->AddAttachment(colorAttachment.resolveTarget,
                                            AttachmentType::ResolveTarget));

    return {};
}

MaybeError ValidateRenderPassDepthStencilAttachment(
    DeviceBase* device,
    const RenderPassDepthStencilAttachment* depthStencilAttachment,
    UsageValidationMode usageValidationMode,
    RenderPassValidationState* validationState) {
    DAWN_CHECK(depthStencilAttachment != nullptr);
    UnpackedPtr<RenderPassDepthStencilAttachment> unpacked;
    DAWN_TRY_ASSIGN(unpacked, ValidateAndUnpack(depthStencilAttachment));

    TextureViewBase* attachment = unpacked->view;
    DAWN_TRY(device->ValidateObject(attachment));
    DAWN_TRY(
        ValidateCanUseAs(attachment, wgpu::TextureUsage::RenderAttachment, usageValidationMode));

    // DS attachments must encompass all aspects of the texture, so we first check that this is
    // true, which means that in the rest of the function we can assume that the view's format is
    // the same as the texture's format.
    const Format& format = attachment->GetTexture()->GetFormat();
    DAWN_INVALID_IF(
        attachment->GetAspects() != format.aspects,
        "The depth stencil attachment %s must encompass all aspects of it's texture's format (%s).",
        attachment, format.format);
    DAWN_CHECK(attachment->GetFormat().format == format.format);

    DAWN_INVALID_IF(!format.HasDepthOrStencil(),
                    "The depth stencil attachment %s format (%s) is not a depth stencil format.",
                    attachment, format.format);

    DAWN_INVALID_IF(!format.IsRenderable(),
                    "The depth stencil attachment %s format (%s) is not renderable.", attachment,
                    format.format);

    // Read only, or depth doesn't exist.
    bool hasDepthAspect = IsSubset(Aspect::Depth, attachment->GetAspects());
    if (unpacked->depthReadOnly || !hasDepthAspect) {
        DAWN_INVALID_IF(unpacked->depthLoadOp != wgpu::LoadOp::Undefined ||
                            unpacked->depthStoreOp != wgpu::StoreOp::Undefined,
                        "Both depthLoadOp (%s) and depthStoreOp (%s) must not be set if the "
                        "attachment (%s) has no depth aspect or depthReadOnly (%u) is true.",
                        unpacked->depthLoadOp, unpacked->depthStoreOp, attachment,
                        unpacked->depthReadOnly);
    } else {
        DAWN_TRY(ValidateLoadOp(unpacked->depthLoadOp));
        DAWN_TRY(ValidateStoreOp(unpacked->depthStoreOp));
        DAWN_INVALID_IF(unpacked->depthLoadOp == wgpu::LoadOp::Undefined ||
                            unpacked->depthStoreOp == wgpu::StoreOp::Undefined,
                        "Both depthLoadOp (%s) and depthStoreOp (%s) must be set if the attachment "
                        "(%s) has a depth aspect or depthReadOnly (%u) is false.",
                        unpacked->depthLoadOp, unpacked->depthStoreOp, attachment,
                        unpacked->depthReadOnly);
    }

    DAWN_INVALID_IF(unpacked->depthLoadOp == wgpu::LoadOp::ExpandResolveTexture ||
                        unpacked->stencilLoadOp == wgpu::LoadOp::ExpandResolveTexture,
                    "%s is not supported on depth/stencil attachment",
                    wgpu::LoadOp::ExpandResolveTexture);

    // Read only, or stencil doesn't exist.
    bool hasStencilAspect = IsSubset(Aspect::Stencil, attachment->GetAspects());
    if (unpacked->stencilReadOnly || !hasStencilAspect) {
        DAWN_INVALID_IF(unpacked->stencilLoadOp != wgpu::LoadOp::Undefined ||
                            unpacked->stencilStoreOp != wgpu::StoreOp::Undefined,
                        "Both stencilLoadOp (%s) and stencilStoreOp (%s) must not be set if the "
                        "attachment (%s) has no stencil aspect or stencilReadOnly (%u) is true.",
                        unpacked->stencilLoadOp, unpacked->stencilStoreOp, attachment,
                        unpacked->stencilReadOnly);
    } else {
        DAWN_TRY(ValidateLoadOp(unpacked->stencilLoadOp));
        DAWN_TRY(ValidateStoreOp(unpacked->stencilStoreOp));
        DAWN_INVALID_IF(unpacked->stencilLoadOp == wgpu::LoadOp::Undefined ||
                            unpacked->stencilStoreOp == wgpu::StoreOp::Undefined,
                        "Both stencilLoadOp (%s) and stencilStoreOp (%s) must be set if the "
                        "attachment (%s) has a stencil aspect or stencilReadOnly (%u) is false.",
                        unpacked->stencilLoadOp, unpacked->stencilStoreOp, attachment,
                        unpacked->stencilReadOnly);
    }
    if (attachment->GetUsage() & wgpu::TextureUsage::TransientAttachment) {
        DAWN_INVALID_IF(hasDepthAspect && unpacked->depthLoadOp != wgpu::LoadOp::Clear,
                        "depthLoadOp (%s) is not %s when the attachment (%s) has a depth aspect "
                        "and its usage (%s) contains %s.",
                        unpacked->depthLoadOp, wgpu::LoadOp::Clear, attachment,
                        attachment->GetUsage(), wgpu::TextureUsage::TransientAttachment);
        DAWN_INVALID_IF(hasStencilAspect && unpacked->stencilLoadOp != wgpu::LoadOp::Clear,
                        "stencilLoadOp (%s) is not %s when the attachment (%s) has a stencil "
                        "aspect and its usage (%s) contains %s.",
                        unpacked->stencilLoadOp, wgpu::LoadOp::Clear, attachment,
                        attachment->GetUsage(), wgpu::TextureUsage::TransientAttachment);
        DAWN_INVALID_IF(hasDepthAspect && unpacked->depthStoreOp != wgpu::StoreOp::Discard,
                        "depthStoreOp (%s) is not %s when the attachment (%s) has a depth aspect "
                        "and its usage (%s) contains %s.",
                        unpacked->depthStoreOp, wgpu::StoreOp::Discard, attachment,
                        attachment->GetUsage(), wgpu::TextureUsage::TransientAttachment);
        DAWN_INVALID_IF(hasStencilAspect && unpacked->stencilStoreOp != wgpu::StoreOp::Discard,
                        "stencilStoreOp (%s) is not %s when the attachment (%s) has a stencil "
                        "aspect and its usage (%s) contains %s.",
                        unpacked->stencilStoreOp, wgpu::StoreOp::Discard, attachment,
                        attachment->GetUsage(), wgpu::TextureUsage::TransientAttachment);
    }

    if (unpacked->depthLoadOp == wgpu::LoadOp::Clear &&
        IsSubset(Aspect::Depth, attachment->GetAspects())) {
        DAWN_INVALID_IF(
            std::isnan(unpacked->depthClearValue),
            "depthClearValue (%f) must be set and must not be a NaN value if the attachment "
            "(%s) has a depth aspect and depthLoadOp is clear.",
            unpacked->depthClearValue, attachment);
        DAWN_INVALID_IF(unpacked->depthClearValue < 0.0f || unpacked->depthClearValue > 1.0f,
                        "depthClearValue (%f) must be between 0.0 and 1.0 if the attachment (%s) "
                        "has a depth aspect and depthLoadOp is clear.",
                        unpacked->depthClearValue, attachment);
    }

    DAWN_TRY(ValidateAttachmentArrayLayersAndLevelCount(attachment));

    // TODO(450506641): Precompute allowed usages of texture views (including swizzle identity
    // check) instead of recomputing.
    DAWN_INVALID_IF(!attachment->IsSwizzleIdentity(),
                    "The depth stencil attachment swizzle must be identity.");

    DAWN_TRY(validationState->AddAttachment(attachment, AttachmentType::DepthStencilAttachment));

    return {};
}

MaybeError ValidateRenderPassPLS(DeviceBase* device,
                                 const RenderPassPixelLocalStorage* pls,
                                 UsageValidationMode usageValidationMode,
                                 RenderPassValidationState* validationState) {
    absl::InlinedVector<StorageAttachmentInfoForValidation, 4> attachments;

    for (auto [i, attachment] : Enumerate(pls->storageAttachments)) {
        // Validate the attachment can be used as a storage attachment.
        DAWN_TRY(device->ValidateObject(attachment.storage));
        DAWN_TRY(ValidateCanUseAs(attachment.storage, wgpu::TextureUsage::StorageAttachment,
                                  usageValidationMode));
        DAWN_TRY(ValidateAttachmentArrayLayersAndLevelCount(attachment.storage));

        // Validate the load/storeOp and the clearValue.
        DAWN_TRY(ValidateLoadOp(attachment.loadOp));
        DAWN_TRY(ValidateStoreOp(attachment.storeOp));
        DAWN_INVALID_IF(attachment.loadOp == wgpu::LoadOp::Undefined,
                        "storageAttachments[%i].loadOp must be set.", i);
        DAWN_INVALID_IF(attachment.storeOp == wgpu::StoreOp::Undefined,
                        "storageAttachments[%i].storeOp must be set.", i);

        const dawn::native::Color& clearValue = attachment.clearValue;
        if (attachment.loadOp == wgpu::LoadOp::Clear) {
            DAWN_TRY(ValidateColor("clearValue", clearValue));
        }

        DAWN_TRY(
            validationState->AddAttachment(attachment.storage, AttachmentType::StorageAttachment));

        attachments.push_back({attachment.offset, attachment.storage->GetFormat().format});
    }

    return ValidatePLSInfo(device, pls->totalPixelLocalStorageSize, attachments);
}

MaybeError ValidateRenderPassDescriptor(DeviceBase* device,
                                        UnpackedPtr<RenderPassDescriptor> descriptor,
                                        UsageValidationMode usageValidationMode,
                                        RenderPassValidationState* validationState) {
    auto maxColorAttachments =
        ColorAttachmentIndex{static_cast<uint8_t>(device->GetLimits().v1.maxColorAttachments)};
    DAWN_INVALID_IF(
        descriptor->colorAttachments.size() > maxColorAttachments,
        "Color attachment count (%u) exceeds the maximum number of color attachments (%u).%s",
        descriptor->colorAttachments.size(), maxColorAttachments,
        DAWN_INCREASE_LIMIT_MESSAGE(device->GetAdapter()->GetLimits().v1, maxColorAttachments,
                                    uint8_t{descriptor->colorAttachments.size()}));

    ColorAttachmentFormats colorAttachmentFormats;
    if (const auto* expandResolveRect = descriptor.Get<RenderPassDescriptorResolveRect>()) {
        DAWN_INVALID_IF(!device->HasFeature(Feature::DawnPartialLoadResolveTexture),
                        "RenderPassDescriptorResolveRect can't be used without %s.",
                        ToAPI(Feature::DawnPartialLoadResolveTexture));
        validationState->SetExpandResolveRect(*expandResolveRect);
    }

    const auto* renderPassSampleCount = descriptor.Get<DawnRenderPassSampleCount>();
    if (renderPassSampleCount) {
        DAWN_TRY(ValidateDawnRenderPassSampleCount(device, renderPassSampleCount));
        validationState->SetExplicitSampleCount(renderPassSampleCount->sampleCount);
    }

    for (auto [i, attachment] : Enumerate(descriptor->colorAttachments)) {
        DAWN_TRY_CONTEXT(ValidateRenderPassColorAttachment(device, attachment, usageValidationMode,
                                                           validationState),
                         "validating colorAttachments[%u].", i);
        if (attachment.view) {
            if (renderPassSampleCount) {
                DAWN_TRY(ValidateColorAttachmentRenderToSingleSampled(device, attachment,
                                                                      renderPassSampleCount));
            }
            colorAttachmentFormats.push_back(&attachment.view->GetFormat());
        }
    }
    DAWN_TRY_CONTEXT(ValidateColorAttachmentBytesPerSample(device, colorAttachmentFormats),
                     "validating color attachment bytes per sample.");

    if (descriptor->depthStencilAttachment != nullptr) {
        DAWN_TRY_CONTEXT(
            ValidateRenderPassDepthStencilAttachment(device, descriptor->depthStencilAttachment,
                                                     usageValidationMode, validationState),
            "validating depthStencilAttachment.");
    }

    if (descriptor->occlusionQuerySet != nullptr) {
        DAWN_TRY(device->ValidateObject(descriptor->occlusionQuerySet));

        DAWN_INVALID_IF(descriptor->occlusionQuerySet->GetQueryType() != wgpu::QueryType::Occlusion,
                        "The occlusionQuerySet %s type (%s) is not %s.",
                        descriptor->occlusionQuerySet,
                        descriptor->occlusionQuerySet->GetQueryType(), wgpu::QueryType::Occlusion);
    }

    if (descriptor->timestampWrites != nullptr) {
        DAWN_TRY_CONTEXT(ValidatePassTimestampWrites(device, descriptor->timestampWrites),
                         "validating timestampWrites.");
    }

    // Validation for any pixel local storage.
    auto pls = descriptor.Get<RenderPassPixelLocalStorage>();
    if (pls != nullptr) {
        DAWN_TRY(ValidateRenderPassPLS(device, pls, usageValidationMode, validationState));
    }

    DAWN_INVALID_IF(!validationState->HasAttachment(), "Render pass has no attachments.");

    if (validationState->IsMsrtssAllowed()) {
        // TODO(dawn:1704): Consider supporting MSAARenderToSingleSampled + PLS
        DAWN_INVALID_IF(
            pls != nullptr,
            "For now pixel local storage is invalid to use with MSAARenderToSingleSampled.");
    }

    if (validationState->WillExpandResolveTexture()) {
        // TODO(dawn:1704): Consider supporting ExpandResolveTexture + PLS
        DAWN_INVALID_IF(pls != nullptr, "For now pixel local storage is invalid to use with %s.",
                        wgpu::LoadOp::ExpandResolveTexture);
    }

    if (auto area = descriptor.Get<RenderPassRenderAreaRect>()) {
        DAWN_INVALID_IF(!device->HasFeature(Feature::RenderPassRenderArea),
                        "RenderPassRenderAreaRect can't be used without %s.",
                        ToAPI(Feature::RenderPassRenderArea));
        DAWN_INVALID_IF(area->size.width == 0 || area->size.height == 0,
                        "RenderPassRenderAreaRect %s must not be empty", area);
        DAWN_INVALID_IF(
            static_cast<uint64_t>(area->origin.x) + static_cast<uint64_t>(area->size.width) >
                    validationState->GetRenderWidth() ||
                static_cast<uint64_t>(area->origin.y) + static_cast<uint64_t>(area->size.height) >
                    validationState->GetRenderHeight(),
            "RenderPassRenderAreaRect %s is not contained in the render pass (%u x %u)", area,
            validationState->GetRenderWidth(), validationState->GetRenderHeight());
    }

    return {};
}

// Adds a single attachment to the validation state to ensure that it is valid and can report a
// render width and height.
MaybeError InitializeValidationStateAttachment(DeviceBase* device,
                                               UnpackedPtr<RenderPassDescriptor> descriptor,
                                               RenderPassValidationState* validationState) {
    TextureViewBase* representativeView = nullptr;

    // Check every attachment to guard against invalid objects caused by OOM errors.
    auto CheckAttachment = [&](TextureViewBase* view) -> MaybeError {
        DAWN_CHECK(view);
        DAWN_TRY(device->IsNotErrorObject(view));
        representativeView = view;
        return {};
    };

    if (auto pls = descriptor.Get<RenderPassPixelLocalStorage>()) {
        for (const RenderPassStorageAttachment& attachment : pls->storageAttachments) {
            DAWN_TRY(CheckAttachment(attachment.storage));
        }
    }

    if (descriptor->depthStencilAttachment != nullptr) {
        DAWN_TRY(CheckAttachment(descriptor->depthStencilAttachment->view));
    }

    for (const RenderPassColorAttachment& colorAttachment : descriptor->colorAttachments) {
        if (colorAttachment.view != nullptr) {
            DAWN_TRY(CheckAttachment(colorAttachment.view));
            if (colorAttachment.resolveTarget != nullptr) {
                DAWN_TRY(device->IsNotErrorObject(colorAttachment.resolveTarget));
            }
        }
    }

    // Only one attachment needs to be added to the validation state.
    DAWN_CHECK(representativeView);
    validationState->SetUnvalidatedAttachment(representativeView);

    return {};
}

MaybeError ValidateComputePassDescriptor(const DeviceBase* device,
                                         const ComputePassDescriptor* descriptor) {
    if (descriptor == nullptr) {
        return {};
    }

    if (descriptor->timestampWrites != nullptr) {
        DAWN_TRY_CONTEXT(ValidatePassTimestampWrites(device, descriptor->timestampWrites),
                         "validating timestampWrites.");
    }

    return {};
}

MaybeError ValidateQuerySetResolve(const QuerySetBase* querySet,
                                   QueryIndex firstQuery,
                                   QueryIndex queryCount,
                                   const BufferBase* destination,
                                   uint64_t destinationOffset) {
    DAWN_INVALID_IF(firstQuery >= querySet->GetQueryCount(),
                    "First query (%u) exceeds the number of queries (%u) in %s.", firstQuery,
                    querySet->GetQueryCount(), querySet);

    DAWN_INVALID_IF(
        queryCount > querySet->GetQueryCount() - firstQuery,
        "The query range (firstQuery: %u, queryCount: %u) exceeds the number of queries "
        "(%u) in %s.",
        firstQuery, queryCount, querySet->GetQueryCount(), querySet);

    DAWN_INVALID_IF(destinationOffset % kQueryResolveAlignment != 0,
                    "The destination buffer %s offset (%u) is not a multiple of %u.", destination,
                    destinationOffset, kQueryResolveAlignment);

    uint64_t bufferSize = destination->GetSize();
    // The destination buffer must have enough storage, from destination offset, to contain
    // the result of resolved queries
    bool fitsInBuffer =
        destinationOffset <= bufferSize &&
        (static_cast<uint64_t>(queryCount) * sizeof(uint64_t) <= (bufferSize - destinationOffset));
    DAWN_INVALID_IF(
        !fitsInBuffer,
        "The resolved %s data size (%u) would not fit in %s with size %u at the offset %u.",
        querySet, static_cast<uint64_t>(queryCount) * sizeof(uint64_t), destination, bufferSize,
        destinationOffset);

    return {};
}

MaybeError EncodeTimestampsToNanosecondsConversion(CommandEncoder* encoder,
                                                   QuerySetBase* querySet,
                                                   QueryIndex firstQuery,
                                                   QueryIndex queryCount,
                                                   BufferBase* destination,
                                                   uint64_t destinationOffset) {
    DeviceBase* device = encoder->GetDevice();

    const uint32_t quantizationMask = device->IsToggleEnabled(Toggle::TimestampQuantization)
                                          ? kTimestampQuantizationMask
                                          : 0xFFFFFFFF;

    // Timestamp params uniform buffer
    TimestampParams params(uint32_t{queryCount}, static_cast<uint32_t>(destinationOffset),
                           quantizationMask, device->GetTimestampPeriodInNS());

    BufferDescriptor parmsDesc = {};
    parmsDesc.usage = wgpu::BufferUsage::Uniform | wgpu::BufferUsage::CopyDst;
    parmsDesc.size = sizeof(params);
    Ref<BufferBase> paramsBuffer;
    DAWN_TRY_ASSIGN(paramsBuffer, device->CreateBuffer(&parmsDesc));

    DAWN_TRY(device->GetQueue()->WriteBuffer(paramsBuffer.Get(), 0, ByteSpanFromRef(params)));

    return EncodeConvertTimestampsToNanoseconds(encoder, uint32_t{queryCount}, destination,
                                                paramsBuffer.Get());
}

bool ShouldUseTextureToBufferBlit(const DeviceBase* device,
                                  const Format& format,
                                  const Aspect& aspect,
                                  const Extent3D& copySize) {
    // Noop copy, do not use blit.
    if (copySize.width == 0 || copySize.height == 0 || copySize.depthOrArrayLayers == 0) {
        return false;
    }

    // Snorm
    if (format.IsSnorm() && device->IsToggleEnabled(Toggle::UseBlitForSnormTextureToBufferCopy)) {
        return true;
    }
    // BGRA8Unorm
    if (format.format == wgpu::TextureFormat::BGRA8Unorm &&
        device->IsToggleEnabled(Toggle::UseBlitForBGRA8UnormTextureToBufferCopy)) {
        return true;
    }
    // RGB9E5Ufloat
    if (format.format == wgpu::TextureFormat::RGB9E5Ufloat &&
        device->IsToggleEnabled(Toggle::UseBlitForRGB9E5UfloatTextureCopy)) {
        return true;
    }
    // RG11B10Ufloat
    if (format.format == wgpu::TextureFormat::RG11B10Ufloat &&
        device->IsToggleEnabled(Toggle::UseBlitForRG11B10UfloatTextureCopy)) {
        return true;
    }
    // float16
    if ((format.format == wgpu::TextureFormat::R16Float ||
         format.format == wgpu::TextureFormat::RG16Float ||
         format.format == wgpu::TextureFormat::RGBA16Float) &&
        device->IsToggleEnabled(Toggle::UseBlitForFloat16TextureCopy)) {
        return true;
    }
    // float32
    if ((format.format == wgpu::TextureFormat::R32Float ||
         format.format == wgpu::TextureFormat::RG32Float ||
         format.format == wgpu::TextureFormat::RGBA32Float) &&
        device->IsToggleEnabled(Toggle::UseBlitForFloat32TextureCopy)) {
        return true;
    }
    // Depth
    if (aspect == Aspect::Depth &&
        ((format.format == wgpu::TextureFormat::Depth16Unorm &&
          device->IsToggleEnabled(Toggle::UseBlitForDepth16UnormTextureToBufferCopy)) ||
         (format.format == wgpu::TextureFormat::Depth24Plus &&
          device->IsToggleEnabled(Toggle::UseBlitForDepth24PlusTextureToBufferCopy)) ||
         (format.format == wgpu::TextureFormat::Depth24PlusStencil8 &&
          device->IsToggleEnabled(Toggle::UseBlitForDepth24PlusTextureToBufferCopy)) ||
         (format.format == wgpu::TextureFormat::Depth32Float &&
          device->IsToggleEnabled(Toggle::UseBlitForDepth32FloatTextureToBufferCopy)))) {
        return true;
    }
    // Stencil
    if (aspect == Aspect::Stencil &&
        device->IsToggleEnabled(Toggle::UseBlitForStencilTextureToBufferCopy)) {
        return true;
    }

    if (device->IsToggleEnabled(Toggle::UseBlitForT2B) &&
        IsFormatSupportedByTextureToBufferBlit(format.format)) {
        return true;
    }

    return false;
}

bool ShouldUseT2B2TForT2T(const DeviceBase* device,
                          const Format& srcFormat,
                          const Format& dstFormat) {
    // RGB9E5Ufloat
    if (srcFormat.baseFormat == wgpu::TextureFormat::RGB9E5Ufloat &&
        device->IsToggleEnabled(Toggle::UseBlitForRGB9E5UfloatTextureCopy)) {
        return true;
    }
    // sRGB <-> non-sRGB
    if (srcFormat.format != dstFormat.format && srcFormat.baseFormat == dstFormat.baseFormat &&
        device->IsToggleEnabled(Toggle::UseT2B2TForSRGBTextureCopy)) {
        return true;
    }
    // Snorm
    if (srcFormat.IsSnorm() &&
        device->IsToggleEnabled(Toggle::UseBlitForSnormTextureToBufferCopy)) {
        return true;
    }
    return false;
}

}  // namespace

Color ClampClearColorValueToLegalRange(const Color& originalColor, const Format& format) {
    const AspectInfo& aspectInfo = format.GetAspectInfo(Aspect::Color);
    double minValue = 0;
    double maxValue = 0;
    switch (aspectInfo.baseType) {
        case TextureComponentType::Float: {
            return originalColor;
        }
        case TextureComponentType::Sint: {
            const uint32_t bitsPerComponent =
                (aspectInfo.block.byteSize * 8 / format.componentCount);
            maxValue =
                static_cast<double>((static_cast<uint64_t>(1) << (bitsPerComponent - 1)) - 1);
            minValue = -static_cast<double>(static_cast<uint64_t>(1) << (bitsPerComponent - 1));
            break;
        }
        case TextureComponentType::Uint: {
            const uint32_t bitsPerComponent =
                (aspectInfo.block.byteSize * 8 / format.componentCount);
            maxValue = static_cast<double>((static_cast<uint64_t>(1) << bitsPerComponent) - 1);
            break;
        }
    }

    return {std::clamp(originalColor.r, minValue, maxValue),
            std::clamp(originalColor.g, minValue, maxValue),
            std::clamp(originalColor.b, minValue, maxValue),
            std::clamp(originalColor.a, minValue, maxValue)};
}

ResultOrError<UnpackedPtr<CommandEncoderDescriptor>> ValidateCommandEncoderDescriptor(
    const DeviceBase* device,
    const CommandEncoderDescriptor* descriptor) {
    UnpackedPtr<CommandEncoderDescriptor> unpacked;
    DAWN_TRY_ASSIGN(unpacked, ValidateAndUnpack(descriptor));

    const auto* internalUsageDesc = unpacked.Get<DawnEncoderInternalUsageDescriptor>();
    DAWN_INVALID_IF(internalUsageDesc != nullptr &&
                        !device->APIHasFeature(wgpu::FeatureName::DawnInternalUsages),
                    "%s is not available.", wgpu::FeatureName::DawnInternalUsages);
    return unpacked;
}

// static
Ref<CommandEncoder> CommandEncoder::Create(
    DeviceBase* device,
    const UnpackedPtr<CommandEncoderDescriptor>& descriptor) {
    return AcquireRef(new CommandEncoder(device, descriptor));
}

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

CommandEncoder::CommandEncoder(DeviceBase* device,
                               const UnpackedPtr<CommandEncoderDescriptor>& descriptor)
    : ApiObjectBase(device, descriptor->label), mEncodingContext(device, this) {
    GetObjectTrackingList()->Track(this);

    auto* internalUsageDesc = descriptor.Get<DawnEncoderInternalUsageDescriptor>();
    if (internalUsageDesc != nullptr && internalUsageDesc->useInternalUsages) {
        mUsageValidationMode = UsageValidationMode::Internal;
    } else {
        mUsageValidationMode = UsageValidationMode::Default;
    }
}

CommandEncoder::CommandEncoder(DeviceBase* device, ObjectBase::ErrorTag tag, StringView label)
    : ApiObjectBase(device, tag, label),
      mEncodingContext(device, tag),
      mUsageValidationMode(UsageValidationMode::Default) {}

ObjectType CommandEncoder::GetType() const {
    return ObjectType::CommandEncoder;
}

void CommandEncoder::DestroyImpl(DestroyReason reason) {
    mEncodingContext.Destroy();
}

CommandBufferResourceUsage CommandEncoder::AcquireResourceUsages() {
    return CommandBufferResourceUsage{
        mEncodingContext.AcquireRenderPassUsages(),
        mEncodingContext.AcquireComputePassUsages(),
        std::move(mTopLevelBuffers),
        std::move(mTopLevelTextures),
        std::move(mUsedQuerySets),
    };
}

CommandIterator CommandEncoder::AcquireCommands() {
    return mEncodingContext.AcquireCommands();
}

void CommandEncoder::TrackUsedQuerySet(QuerySetBase* querySet) {
    mUsedQuerySets.insert(querySet);
}

ityp::vector<PassIndex, IndirectDrawMetadata> CommandEncoder::AcquireIndirectDrawMetadata() {
    return mEncodingContext.AcquireIndirectDrawMetadata();
}

// Implementation of the API's command recording methods

ComputePassEncoder* CommandEncoder::APIBeginComputePass(const ComputePassDescriptor* descriptor) {
    // This function will create new object, need to lock the Device.
    auto deviceGuard = GetDevice()->GetGuard();

    return ReturnToAPI(BeginComputePass(descriptor));
}

Ref<ComputePassEncoder> CommandEncoder::BeginComputePass(const ComputePassDescriptor* descriptor) {
    DeviceBase* device = GetDevice();
    DAWN_ASSERT(device->IsLockedByCurrentThreadIfNeeded());

    bool success = mEncodingContext.TryEncode(
        this,
        [&](CommandAllocator* allocator) -> MaybeError {
            if (GetDevice()->IsValidationEnabled()) {
                DAWN_TRY(ValidateComputePassDescriptor(device, descriptor));
            }

            BeginComputePassCmd* cmd =
                allocator->Allocate<BeginComputePassCmd>(Command::BeginComputePass);

            if (descriptor == nullptr) {
                return {};
            }

            if (!descriptor->label.IsUndefined()) {
                cmd->label = std::string(descriptor->label);
            }

            if (descriptor->timestampWrites != nullptr) {
                QuerySetBase* querySet = descriptor->timestampWrites->querySet;
                QueryIndex beginningOfPassWriteIndex{
                    descriptor->timestampWrites->beginningOfPassWriteIndex};
                QueryIndex endOfPassWriteIndex{descriptor->timestampWrites->endOfPassWriteIndex};

                TrackUsedQuerySet(querySet);
                cmd->timestampWrites.querySet = querySet;
                cmd->timestampWrites.beginningOfPassWriteIndex = beginningOfPassWriteIndex;
                cmd->timestampWrites.endOfPassWriteIndex = endOfPassWriteIndex;
            }
            return {};
        },
        "encoding %s.BeginComputePass(%s).", this, descriptor);

    if (success) {
        const ComputePassDescriptor defaultDescriptor = {};
        if (descriptor == nullptr) {
            descriptor = &defaultDescriptor;
        }

        Ref<ComputePassEncoder> passEncoder =
            ComputePassEncoder::Create(device, descriptor, this, &mEncodingContext);
        mEncodingContext.EnterPass(passEncoder.Get());
        return passEncoder;
    }

    return ComputePassEncoder::MakeError(device, this, &mEncodingContext,
                                         descriptor ? descriptor->label : nullptr);
}

RenderPassEncoder* CommandEncoder::APIBeginRenderPass(const RenderPassDescriptor* descriptor) {
    // This function will create new object, need to lock the Device.
    auto deviceGuard = GetDevice()->GetGuard();

    return ReturnToAPI(BeginRenderPass(descriptor));
}

Ref<RenderPassEncoder> CommandEncoder::BeginRenderPass(const RenderPassDescriptor* rawDescriptor) {
    DeviceBase* device = GetDevice();
    DAWN_ASSERT(device->IsLockedByCurrentThreadIfNeeded());

    RenderPassResourceUsageTracker usageTracker;

    bool depthReadOnly = false;
    bool stencilReadOnly = false;
    Ref<AttachmentState> attachmentState;

    RenderPassValidationState validationState;

    // Lazy make error function to be called if we error and need to return an error encoder.
    auto MakeError = [&]() {
        return RenderPassEncoder::MakeError(device, this, &mEncodingContext,
                                            rawDescriptor ? rawDescriptor->label : nullptr);
    };

    UnpackedPtr<RenderPassDescriptor> descriptor;
    ClearWithDrawHelper clearWithDrawHelper;
    RenderPassWorkaroundsHelper renderpassWorkaroundsHelper;

    RenderPassEncoder::EndCallback passEndCallback = nullptr;

    RenderAreaRect renderArea;

    bool success = mEncodingContext.TryEncode(
        this,
        [&](CommandAllocator* allocator) -> MaybeError {
            DAWN_TRY_ASSIGN_CONTEXT(descriptor, ValidateAndUnpack(rawDescriptor),
                                    "validating and unpacking chained structs.");

            if (GetDevice()->IsValidationEnabled()) {
                DAWN_TRY(ValidateRenderPassDescriptor(device, descriptor, mUsageValidationMode,
                                                      &validationState));
            } else {
                // If validation is skipped at least one attachment still needs to be added to the
                // validation state to compute the render width and height from.
                DAWN_TRY(InitializeValidationStateAttachment(device, descriptor, &validationState));
            }

            DAWN_CHECK(validationState.IsValidState());

            DAWN_TRY(clearWithDrawHelper.Initialize(this, descriptor));
            DAWN_TRY(renderpassWorkaroundsHelper.Initialize(this, descriptor));

            mEncodingContext.WillBeginRenderPass();
            BeginRenderPassCmd* cmd =
                allocator->Allocate<BeginRenderPassCmd>(Command::BeginRenderPass);

            if (!descriptor->label.IsUndefined()) {
                cmd->label = std::string(descriptor->label);
            }

            cmd->attachmentState = device->GetOrCreateAttachmentState(descriptor);
            attachmentState = cmd->attachmentState;

            for (auto i : cmd->attachmentState->GetColorAttachmentsMask()) {
                auto& descColorAttachment = descriptor->colorAttachments[i];
                auto& cmdColorAttachment = cmd->colorAttachments[i];

                TextureViewBase* colorTarget;
                TextureViewBase* resolveTarget;

                colorTarget = descColorAttachment.view;
                resolveTarget = descColorAttachment.resolveTarget;

                cmdColorAttachment.view = colorTarget;
                // Explicitly set depthSlice to 0 if it's undefined. The
                // wgpu::kDepthSliceUndefined is defined to differentiate between `undefined`
                // and 0 for depthSlice, but we use it as 0 for 2d attachments in backends.
                cmdColorAttachment.depthSlice =
                    descColorAttachment.depthSlice == wgpu::kDepthSliceUndefined
                        ? 0
                        : descColorAttachment.depthSlice;
                cmdColorAttachment.loadOp = descColorAttachment.loadOp;
                cmdColorAttachment.storeOp = descColorAttachment.storeOp;

                cmdColorAttachment.resolveTarget = resolveTarget;
                cmdColorAttachment.clearColor = ClampClearColorValueToLegalRange(
                    descColorAttachment.clearValue, colorTarget->GetFormat());

                usageTracker.TextureViewUsedAs(colorTarget, wgpu::TextureUsage::RenderAttachment);

                if (resolveTarget != nullptr) {
                    usageTracker.TextureViewUsedAs(resolveTarget,
                                                   wgpu::TextureUsage::RenderAttachment);
                } else if (colorTarget->GetTexture()->GetSampleCount() == 1 &&
                           attachmentState->GetSampleCount() > 1) {
                    // Detect if multisample render to single-sampled is in use
                    cmd->msaaRenderToSingleSampled = true;
                }
            }

            if (cmd->attachmentState->HasDepthStencilAttachment()) {
                TextureViewBase* view = descriptor->depthStencilAttachment->view;
                TextureBase* attachment = view->GetTexture();
                cmd->depthStencilAttachment.view = view;
                // Range that will be modified per aspect to track the usage.
                SubresourceRange usageRange = view->GetSubresourceRange();

                switch (descriptor->depthStencilAttachment->depthLoadOp) {
                    case wgpu::LoadOp::Clear:
                        cmd->depthStencilAttachment.clearDepth =
                            descriptor->depthStencilAttachment->depthClearValue;
                        break;
                    case wgpu::LoadOp::Load:
                    case wgpu::LoadOp::Undefined:
                        // Set depthClearValue to 0 if it is the load op is not clear.
                        // The default value NaN may be invalid in the backend.
                        cmd->depthStencilAttachment.clearDepth = 0.f;
                        break;
                    case wgpu::LoadOp::ExpandResolveTexture:
                        DAWN_UNREACHABLE();
                        break;
                }

                // GPURenderPassDepthStencilAttachment.stencilClearValue will be converted to
                // the type of the stencil aspect of view by taking the same number of LSBs as
                // the number of bits in the stencil aspect of one texel block of view.
                DAWN_CHECK(!(view->GetFormat().aspects & Aspect::Stencil) ||
                           view->GetFormat().GetAspectInfo(Aspect::Stencil).block.byteSize == 1u);
                cmd->depthStencilAttachment.clearStencil =
                    descriptor->depthStencilAttachment->stencilClearValue & 0xFF;

                // Depth aspect:
                //  - Copy parameters for the aspect, reyifing the values when it is not present or
                //  readonly.
                //  - Export depthReadOnly to the outside of the depth-stencil attachment handling.
                //  - Track the usage of this aspect.
                depthReadOnly = descriptor->depthStencilAttachment->depthReadOnly;

                cmd->depthStencilAttachment.depthReadOnly = false;
                cmd->depthStencilAttachment.depthLoadOp = wgpu::LoadOp::Load;
                cmd->depthStencilAttachment.depthStoreOp = wgpu::StoreOp::Store;
                if (attachment->GetFormat().HasDepth()) {
                    cmd->depthStencilAttachment.depthReadOnly = depthReadOnly;
                    if (!depthReadOnly) {
                        cmd->depthStencilAttachment.depthLoadOp =
                            descriptor->depthStencilAttachment->depthLoadOp;
                        cmd->depthStencilAttachment.depthStoreOp =
                            descriptor->depthStencilAttachment->depthStoreOp;
                    }

                    usageRange.aspects = Aspect::Depth;
                    usageTracker.TextureRangeUsedAs(attachment, usageRange,
                                                    depthReadOnly
                                                        ? kReadOnlyRenderAttachment
                                                        : wgpu::TextureUsage::RenderAttachment);
                }

                // Stencil aspect:
                //  - Copy parameters for the aspect, reyifing the values when it is not present or
                //  readonly.
                //  - Export stencilReadOnly to the outside of the depth-stencil attachment
                //  handling.
                //  - Track the usage of this aspect.
                stencilReadOnly = descriptor->depthStencilAttachment->stencilReadOnly;

                cmd->depthStencilAttachment.stencilReadOnly = false;
                cmd->depthStencilAttachment.stencilLoadOp = wgpu::LoadOp::Load;
                cmd->depthStencilAttachment.stencilStoreOp = wgpu::StoreOp::Store;
                if (attachment->GetFormat().HasStencil()) {
                    cmd->depthStencilAttachment.stencilReadOnly = stencilReadOnly;
                    if (!stencilReadOnly) {
                        cmd->depthStencilAttachment.stencilLoadOp =
                            descriptor->depthStencilAttachment->stencilLoadOp;
                        cmd->depthStencilAttachment.stencilStoreOp =
                            descriptor->depthStencilAttachment->stencilStoreOp;
                    }

                    usageRange.aspects = Aspect::Stencil;
                    usageTracker.TextureRangeUsedAs(attachment, usageRange,
                                                    stencilReadOnly
                                                        ? kReadOnlyRenderAttachment
                                                        : wgpu::TextureUsage::RenderAttachment);
                }
            }

            cmd->width = validationState.GetRenderWidth();
            cmd->height = validationState.GetRenderHeight();

            if (auto* area = descriptor.Get<RenderPassRenderAreaRect>()) {
                renderArea.x = area->origin.x;
                renderArea.y = area->origin.y;
                renderArea.width = area->size.width;
                renderArea.height = area->size.height;
            } else {
                renderArea.x = 0;
                renderArea.y = 0;
                renderArea.width = validationState.GetRenderWidth();
                renderArea.height = validationState.GetRenderHeight();
            }

            cmd->renderArea = renderArea;

            if (descriptor->occlusionQuerySet) {
                TrackUsedQuerySet(descriptor->occlusionQuerySet);
                cmd->occlusionQuerySet = descriptor->occlusionQuerySet;
            }

            if (descriptor->timestampWrites != nullptr) {
                QuerySetBase* querySet = descriptor->timestampWrites->querySet;
                QueryIndex beginningOfPassWriteIndex{
                    descriptor->timestampWrites->beginningOfPassWriteIndex};
                QueryIndex endOfPassWriteIndex{descriptor->timestampWrites->endOfPassWriteIndex};

                TrackUsedQuerySet(querySet);
                cmd->timestampWrites.querySet = querySet;
                cmd->timestampWrites.beginningOfPassWriteIndex = beginningOfPassWriteIndex;
                cmd->timestampWrites.endOfPassWriteIndex = endOfPassWriteIndex;

                // The render pass usage tracker contains data about written queries. This is
                // necessary on Vulkan to be able to reset queries before the start of render passes
                // (it can only be done outside of a render pass).
                if (beginningOfPassWriteIndex != kQuerySetIndexUndefinedTyped) {
                    usageTracker.TrackQueryAvailability(querySet, beginningOfPassWriteIndex);
                }
                if (endOfPassWriteIndex != kQuerySetIndexUndefinedTyped) {
                    usageTracker.TrackQueryAvailability(querySet, endOfPassWriteIndex);
                }
            }

            if (auto* pls = descriptor.Get<RenderPassPixelLocalStorage>()) {
                for (const RenderPassStorageAttachment& attachment : pls->storageAttachments) {
                    RenderPassStorageAttachmentInfo* attachmentInfo =
                        &cmd->storageAttachments[attachment.offset / kPLSSlotByteSize];

                    attachmentInfo->storage = attachment.storage;
                    attachmentInfo->loadOp = attachment.loadOp;
                    attachmentInfo->storeOp = attachment.storeOp;
                    attachmentInfo->clearColor = ClampClearColorValueToLegalRange(
                        attachment.clearValue, attachment.storage->GetFormat());

                    usageTracker.TextureViewUsedAs(attachment.storage,
                                                   wgpu::TextureUsage::StorageAttachment);
                }
            }

            DAWN_TRY(renderpassWorkaroundsHelper.ApplyOnPostEncoding(
                this, descriptor, &usageTracker, cmd, &passEndCallback));

            return {};
        },
        "encoding %s.BeginRenderPass(%s).", this, descriptor);

    if (success) {
        Ref<RenderPassEncoder> passEncoder =
            RenderPassEncoder::Create(device, descriptor, this, &mEncodingContext,
                                      std::move(usageTracker), std::move(attachmentState),
                                      renderArea, depthReadOnly, stencilReadOnly, passEndCallback);

        mEncodingContext.EnterPass(passEncoder.Get());

        auto error = [&]() -> MaybeError {
            // clearWithDrawHelper.Apply() applies clear with draw if clear_color_with_draw or
            // apply_clear_big_integer_color_value_with_draw toggle is enabled, and the render pass
            // attachments need to be cleared.
            // TODO(341129591): move inside RenderPassWorkaroundsHelper.
            DAWN_TRY(clearWithDrawHelper.Apply(passEncoder.Get()));

            DAWN_TRY(
                renderpassWorkaroundsHelper.ApplyOnRenderPassStart(passEncoder.Get(), descriptor));

            return {};
        }();

        if (device->ConsumedError(std::move(error))) {
            return MakeError();
        }

        return passEncoder;
    }

    return MakeError();
}

void CommandEncoder::APICopyBufferToBuffer(BufferBase* source,
                                           uint64_t sourceOffset,
                                           BufferBase* destination,
                                           uint64_t destinationOffset,
                                           uint64_t size) {
    mEncodingContext.TryEncode(
        this,
        [&](CommandAllocator* allocator) -> MaybeError {
            if (GetDevice()->IsValidationEnabled()) {
                DAWN_TRY(GetDevice()->ValidateObject(source));
                DAWN_TRY(GetDevice()->ValidateObject(destination));

                DAWN_INVALID_IF(source == destination,
                                "Source and destination are the same buffer (%s).", source);

                DAWN_TRY_CONTEXT(ValidateCopySizeFitsInBuffer(source, sourceOffset, size),
                                 "validating source %s copy size.", source);
                DAWN_TRY_CONTEXT(ValidateCopySizeFitsInBuffer(destination, destinationOffset, size),
                                 "validating destination %s copy size.", destination);
                DAWN_TRY(ValidateB2BCopyAlignment(size, sourceOffset, destinationOffset));

                DAWN_TRY_CONTEXT(ValidateCanUseAs(source, wgpu::BufferUsage::CopySrc),
                                 "validating source %s usage.", source);
                DAWN_TRY_CONTEXT(ValidateCanUseAs(destination, wgpu::BufferUsage::CopyDst),
                                 "validating destination %s usage.", destination);
            }

            mTopLevelBuffers.insert(source);
            mTopLevelBuffers.insert(destination);

            CopyBufferToBufferCmd* copy =
                allocator->Allocate<CopyBufferToBufferCmd>(Command::CopyBufferToBuffer);
            copy->source = source;
            copy->sourceOffset = sourceOffset;
            copy->destination = destination;
            copy->destinationOffset = destinationOffset;
            copy->size = size;

            return {};
        },
        "encoding %s.CopyBufferToBuffer(%s, %u, %s, %u, %u).", this, source, sourceOffset,
        destination, destinationOffset, size);
}

// The internal version of APICopyBufferToBuffer which validates against mAllocatedSize instead of
// mSize of buffers.
void CommandEncoder::InternalCopyBufferToBufferWithAllocatedSize(BufferBase* source,
                                                                 uint64_t sourceOffset,
                                                                 BufferBase* destination,
                                                                 uint64_t destinationOffset,
                                                                 uint64_t size) {
    mEncodingContext.TryEncode(
        this,
        [&](CommandAllocator* allocator) -> MaybeError {
            if (GetDevice()->IsValidationEnabled()) {
                DAWN_TRY(GetDevice()->ValidateObject(source));
                DAWN_TRY(GetDevice()->ValidateObject(destination));

                DAWN_INVALID_IF(source == destination,
                                "Source and destination are the same buffer (%s).", source);

                DAWN_TRY_CONTEXT(ValidateCopySizeFitsInBuffer(source, sourceOffset, size,
                                                              BufferSizeType::AllocatedSize),
                                 "validating source %s copy size against allocated size.", source);
                DAWN_TRY_CONTEXT(ValidateCopySizeFitsInBuffer(destination, destinationOffset, size,
                                                              BufferSizeType::AllocatedSize),
                                 "validating destination %s copy size against allocated size.",
                                 destination);
                DAWN_TRY(ValidateB2BCopyAlignment(size, sourceOffset, destinationOffset));

                DAWN_TRY_CONTEXT(ValidateCanUseAsInternal(
                                     source, wgpu::BufferUsage::CopySrc | kInternalCopySrcBuffer),
                                 "validating source %s usage.", source);
                DAWN_TRY_CONTEXT(ValidateCanUseAs(destination, wgpu::BufferUsage::CopyDst),
                                 "validating destination %s usage.", destination);
            }

            mTopLevelBuffers.insert(source);
            mTopLevelBuffers.insert(destination);

            CopyBufferToBufferCmd* copy =
                allocator->Allocate<CopyBufferToBufferCmd>(Command::CopyBufferToBuffer);
            copy->source = source;
            copy->sourceOffset = sourceOffset;
            copy->destination = destination;
            copy->destinationOffset = destinationOffset;
            copy->size = size;

            return {};
        },
        "encoding internal %s.CopyBufferToBuffer(%s, %u, %s, %u, %u).", this, source, sourceOffset,
        destination, destinationOffset, size);
}

void CommandEncoder::APICopyBufferToTexture(const TexelCopyBufferInfo* source,
                                            const TexelCopyTextureInfo* destinationOrig,
                                            const Extent3D* copySize) {
    TexelCopyTextureInfo destination = destinationOrig->WithTrivialFrontendDefaults();

    mEncodingContext.TryEncode(
        this,
        [&](CommandAllocator* allocator) -> MaybeError {
            if (GetDevice()->IsValidationEnabled()) {
                DAWN_TRY(ValidateTexelCopyBufferInfo(GetDevice(), *source));
                DAWN_TRY_CONTEXT(ValidateCanUseAs(source->buffer, wgpu::BufferUsage::CopySrc),
                                 "validating source %s usage.", source->buffer);

                DAWN_TRY(ValidateTexelCopyTextureInfo(GetDevice(), destination, *copySize));
                DAWN_TRY_CONTEXT(ValidateCanUseAs(destination.texture, wgpu::TextureUsage::CopyDst,
                                                  mUsageValidationMode),
                                 "validating destination %s usage.", destination.texture);
                DAWN_TRY(ValidateTextureSampleCountInBufferCopyCommands(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, *copySize));
            }
            const TypedTexelBlockInfo& blockInfo = GetBlockInfo(destination);
            if (GetDevice()->IsValidationEnabled()) {
                DAWN_TRY(ValidateLinearTextureCopyOffset(
                    source->layout, blockInfo.ToTexelBlockInfo(),
                    destination.texture->GetFormat().HasDepthOrStencil()));
                DAWN_TRY(ValidateLinearTextureData(source->layout, source->buffer->GetSize(),
                                                   blockInfo.ToTexelBlockInfo(), *copySize));
            }

            mTopLevelBuffers.insert(source->buffer);
            mTopLevelTextures.insert(destination.texture);

            TexelCopyBufferLayout srcLayout = source->layout;
            ApplyDefaultTexelCopyBufferLayoutOptions(&srcLayout, blockInfo.ToTexelBlockInfo(),
                                                     *copySize);

            TextureCopy dst;
            dst.texture = destination.texture;
            dst.origin = destination.origin;
            dst.mipLevel = destination.mipLevel;
            dst.aspect = ConvertAspect(destination.texture->GetFormat(), destination.aspect);

            if (dst.aspect == Aspect::Depth &&
                GetDevice()->IsToggleEnabled(Toggle::UseBlitForBufferToDepthTextureCopy)) {
                // The below function might create new resources. Need to lock the Device.
                // 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.
                auto deviceGuard = GetDevice()->GetGuard();

                DAWN_TRY_CONTEXT(
                    BlitBufferToDepth(GetDevice(), this, source->buffer, srcLayout, dst, *copySize),
                    "copying from %s to depth aspect of %s using blit workaround.", source->buffer,
                    dst.texture.Get());
                return {};
            } else if (dst.aspect == Aspect::Stencil &&
                       GetDevice()->IsToggleEnabled(Toggle::UseBlitForBufferToStencilTextureCopy)) {
                // The below function might create new resources. Need to lock the Device.
                // 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.
                auto deviceGuard = GetDevice()->GetGuard();

                DAWN_TRY_CONTEXT(BlitBufferToStencil(GetDevice(), this, source->buffer, srcLayout,
                                                     dst, *copySize),
                                 "copying from %s to stencil aspect of %s using blit workaround.",
                                 source->buffer, dst.texture.Get());
                return {};
            } else if (GetDevice()->IsToggleEnabled(Toggle::UseBlitForB2T) &&
                       IsBufferToTextureBlitSupported(source->buffer, dst, *copySize)) {
                // This function might create new resources. Need to lock the Device.
                // 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.
                auto deviceGuard = GetDevice()->GetGuard();
                DAWN_TRY_CONTEXT(BlitBufferToTexture(GetDevice(), this, source->buffer, srcLayout,
                                                     dst, *copySize),
                                 "copying buffer %s to %s using blit workaround.", source->buffer,
                                 dst.texture.Get());

                return {};
            }

            CopyBufferToTextureCmd* copy =
                allocator->Allocate<CopyBufferToTextureCmd>(Command::CopyBufferToTexture);
            copy->source.buffer = source->buffer;
            copy->source.offset = srcLayout.offset;
            copy->source.blocksPerRow = blockInfo.BytesToBlocks(srcLayout.bytesPerRow);
            copy->source.rowsPerImage = BlockCount{srcLayout.rowsPerImage};
            copy->destination = dst;
            copy->copySize = *copySize;

            return {};
        },
        "encoding %s.CopyBufferToTexture(%s, %s, %s).", this, source->buffer, destination.texture,
        copySize);
}

void CommandEncoder::APICopyTextureToBuffer(const TexelCopyTextureInfo* sourceOrig,
                                            const TexelCopyBufferInfo* destination,
                                            const Extent3D* copySize) {
    TexelCopyTextureInfo source = sourceOrig->WithTrivialFrontendDefaults();

    mEncodingContext.TryEncode(
        this,
        [&](CommandAllocator* allocator) -> MaybeError {
            if (GetDevice()->IsValidationEnabled()) {
                DAWN_TRY(ValidateTexelCopyTextureInfo(GetDevice(), source, *copySize));
                DAWN_TRY_CONTEXT(ValidateCanUseAs(source.texture, wgpu::TextureUsage::CopySrc,
                                                  mUsageValidationMode),
                                 "validating source %s usage.", source.texture);
                DAWN_TRY(ValidateTextureSampleCountInBufferCopyCommands(source.texture));
                DAWN_TRY(ValidateTextureDepthStencilToBufferCopyRestrictions(GetDevice(), source));

                DAWN_TRY(ValidateTexelCopyBufferInfo(GetDevice(), *destination));
                DAWN_TRY_CONTEXT(ValidateCanUseAs(destination->buffer, wgpu::BufferUsage::CopyDst),
                                 "validating destination %s usage.", destination->buffer);

                // 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(), source, *copySize));

                if (GetDevice()->IsCompatibilityMode()) {
                    DAWN_TRY(ValidateTextureFormatForTextureToBufferCopyInCompatibilityMode(
                        source.texture));
                }
            }
            const TypedTexelBlockInfo& blockInfo = GetBlockInfo(source);
            if (GetDevice()->IsValidationEnabled()) {
                DAWN_TRY(ValidateLinearTextureCopyOffset(
                    destination->layout, blockInfo.ToTexelBlockInfo(),
                    source.texture->GetFormat().HasDepthOrStencil()));
                DAWN_TRY(ValidateLinearTextureData(destination->layout,
                                                   destination->buffer->GetSize(),
                                                   blockInfo.ToTexelBlockInfo(), *copySize));
            }

            mTopLevelTextures.insert(source.texture);
            mTopLevelBuffers.insert(destination->buffer);

            TexelCopyBufferLayout dstLayout = destination->layout;
            ApplyDefaultTexelCopyBufferLayoutOptions(&dstLayout, blockInfo.ToTexelBlockInfo(),
                                                     *copySize);

            auto format = source.texture->GetFormat();
            auto aspect = ConvertAspect(format, source.aspect);

            // Workaround to use compute pass to emulate texture to buffer copy
            if (ShouldUseTextureToBufferBlit(GetDevice(), format, aspect, *copySize)) {
                // This function might create new resources. Need to lock the Device.
                // 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.
                auto deviceGuard = GetDevice()->GetGuard();

                TextureCopy src;
                src.texture = source.texture;
                src.origin = source.origin;
                src.mipLevel = source.mipLevel;
                src.aspect = aspect;

                BufferCopy dst;
                dst.buffer = destination->buffer;
                dst.blocksPerRow = blockInfo.BytesToBlocks(dstLayout.bytesPerRow);
                dst.rowsPerImage = BlockCount{dstLayout.rowsPerImage};
                dst.offset = dstLayout.offset;
                DAWN_TRY_CONTEXT(
                    BlitTextureToBuffer(GetDevice(), this, src, dst, blockInfo.ToBlock(*copySize)),
                    "copying texture %s to %s using blit workaround.", src.texture.Get(),
                    destination->buffer);

                return {};
            }

            CopyTextureToBufferCmd* t2b =
                allocator->Allocate<CopyTextureToBufferCmd>(Command::CopyTextureToBuffer);
            t2b->source.texture = source.texture;
            t2b->source.origin = source.origin;
            t2b->source.mipLevel = source.mipLevel;
            t2b->source.aspect = ConvertAspect(source.texture->GetFormat(), source.aspect);
            t2b->destination.buffer = destination->buffer;
            t2b->destination.offset = dstLayout.offset;
            t2b->destination.blocksPerRow = blockInfo.BytesToBlocks(dstLayout.bytesPerRow);
            t2b->destination.rowsPerImage = BlockCount{dstLayout.rowsPerImage};
            t2b->copySize = *copySize;

            return {};
        },
        "encoding %s.CopyTextureToBuffer(%s, %s, %s).", this, source.texture, destination->buffer,
        copySize);
}

void CommandEncoder::APICopyTextureToTexture(const TexelCopyTextureInfo* sourceOrig,
                                             const TexelCopyTextureInfo* destinationOrig,
                                             const Extent3D* copySize) {
    TexelCopyTextureInfo source = sourceOrig->WithTrivialFrontendDefaults();
    TexelCopyTextureInfo destination = destinationOrig->WithTrivialFrontendDefaults();

    mEncodingContext.TryEncode(
        this,
        [&](CommandAllocator* allocator) -> MaybeError {
            if (GetDevice()->IsValidationEnabled()) {
                DAWN_TRY(GetDevice()->ValidateObject(source.texture));
                DAWN_TRY(GetDevice()->ValidateObject(destination.texture));

                DAWN_INVALID_IF(source.texture->GetFormat().IsMultiPlanar() ||
                                    destination.texture->GetFormat().IsMultiPlanar(),
                                "Copying between a multiplanar texture and another texture is "
                                "currently not allowed.");
                DAWN_TRY_CONTEXT(ValidateTexelCopyTextureInfo(GetDevice(), source, *copySize),
                                 "validating source %s.", source.texture);
                DAWN_TRY_CONTEXT(ValidateTexelCopyTextureInfo(GetDevice(), destination, *copySize),
                                 "validating destination %s.", destination.texture);

                DAWN_TRY_CONTEXT(ValidateTextureCopyRange(GetDevice(), source, *copySize),
                                 "validating source %s copy range.", source.texture);
                DAWN_TRY_CONTEXT(ValidateTextureCopyRange(GetDevice(), destination, *copySize),
                                 "validating source %s copy range.", destination.texture);

                DAWN_TRY(ValidateTextureToTextureCopyRestrictions(GetDevice(), source, destination,
                                                                  *copySize));

                DAWN_TRY(ValidateCanUseAs(source.texture, wgpu::TextureUsage::CopySrc,
                                          mUsageValidationMode));
                DAWN_TRY(ValidateCanUseAs(destination.texture, wgpu::TextureUsage::CopyDst,
                                          mUsageValidationMode));

                if (GetDevice()->IsCompatibilityMode()) {
                    DAWN_TRY(ValidateSourceTextureFormatForTextureToTextureCopyInCompatibilityMode(
                        source.texture));
                }
            }

            mTopLevelTextures.insert(source.texture);
            mTopLevelTextures.insert(destination.texture);

            Aspect aspect = ConvertAspect(source.texture->GetFormat(), source.aspect);
            DAWN_CHECK(aspect ==
                       ConvertAspect(destination.texture->GetFormat(), destination.aspect));

            TextureCopy src;
            src.texture = source.texture;
            src.origin = source.origin;
            src.mipLevel = source.mipLevel;
            src.aspect = aspect;

            TextureCopy dst;
            dst.texture = destination.texture;
            dst.origin = destination.origin;
            dst.mipLevel = destination.mipLevel;
            dst.aspect = aspect;

            // Emulate a T2T copy with a T2B copy and a B2T copy.
            if (ShouldUseT2B2TForT2T(GetDevice(), src.texture->GetFormat(),
                                     dst.texture->GetFormat())) {
                // Calculate needed buffer size to hold copied texel data.
                const TexelBlockInfo& blockInfo = GetBlockInfo(source);
                const uint32_t bytesPerRow =
                    Align(4 * copySize->width, kTextureBytesPerRowAlignment);
                const uint32_t rowsPerImage = copySize->height;
                uint64_t requiredBytes;
                DAWN_TRY_ASSIGN(
                    requiredBytes,
                    ComputeRequiredBytesInCopy(blockInfo, *copySize, bytesPerRow, rowsPerImage));

                // Create an intermediate dst buffer.
                BufferDescriptor descriptor = {};
                descriptor.size = Align(requiredBytes, 4);
                descriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst;
                Ref<BufferBase> intermediateBuffer;
                DAWN_TRY_ASSIGN(intermediateBuffer, GetDevice()->CreateBuffer(&descriptor));

                TexelCopyBufferInfo buf;
                buf.buffer = intermediateBuffer.Get();
                buf.layout.bytesPerRow = bytesPerRow;
                buf.layout.rowsPerImage = rowsPerImage;

                APICopyTextureToBuffer(&source, &buf, copySize);
                APICopyBufferToTexture(&buf, &destination, copySize);

                return {};
            }

            const bool blitDepth =
                (aspect & Aspect::Depth) &&
                GetDevice()->IsToggleEnabled(
                    Toggle::UseBlitForDepthTextureToTextureCopyToNonzeroSubresource) &&
                copySize->depthOrArrayLayers > 0 &&
                (dst.mipLevel > 0 || dst.origin.z > TexelCount{0u} ||
                 copySize->depthOrArrayLayers > 1);

            // If we're not using a blit, or there are aspects other than depth,
            // issue the copy. This is because if there's also stencil, we still need the copy
            // command to copy the stencil portion.
            if (!blitDepth || aspect != Aspect::Depth) {
                CopyTextureToTextureCmd* copy =
                    allocator->Allocate<CopyTextureToTextureCmd>(Command::CopyTextureToTexture);
                copy->source = src;
                copy->destination = dst;
                copy->copySize = *copySize;
            }

            // Use a blit to copy the depth aspect.
            if (blitDepth) {
                // This function might create new resources. Need to lock the Device.
                // 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.
                auto deviceGuard = GetDevice()->GetGuard();

                DAWN_TRY_CONTEXT(BlitDepthToDepth(GetDevice(), this, src, dst, *copySize),
                                 "copying depth aspect from %s to %s using blit workaround.",
                                 source.texture, destination.texture);
            }

            return {};
        },
        "encoding %s.CopyTextureToTexture(%s, %s, %s).", this, source.texture, destination.texture,
        copySize);
}

void CommandEncoder::APIClearBuffer(BufferBase* buffer, uint64_t offset, uint64_t size) {
    mEncodingContext.TryEncode(
        this,
        [&](CommandAllocator* allocator) -> MaybeError {
            if (GetDevice()->IsValidationEnabled()) {
                DAWN_TRY(GetDevice()->ValidateObject(buffer));

                uint64_t bufferSize = buffer->GetSize();
                DAWN_INVALID_IF(offset > bufferSize,
                                "Buffer offset (%u) is larger than the size (%u) of %s.", offset,
                                bufferSize, buffer);

                uint64_t remainingSize = bufferSize - offset;
                if (size == wgpu::kWholeSize) {
                    size = remainingSize;
                } else {
                    DAWN_INVALID_IF(size > remainingSize,
                                    "Buffer range (offset: %u, size: %u) doesn't fit in "
                                    "the size (%u) of %s.",
                                    offset, size, bufferSize, buffer);
                }

                DAWN_TRY_CONTEXT(ValidateCanUseAs(buffer, wgpu::BufferUsage::CopyDst),
                                 "validating buffer %s usage.", buffer);

                // Size must be a multiple of 4 bytes on macOS.
                DAWN_INVALID_IF(size % 4 != 0, "Fill size (%u) is not a multiple of 4 bytes.",
                                size);

                // Offset must be multiples of 4 bytes on macOS.
                DAWN_INVALID_IF(offset % 4 != 0, "Offset (%u) is not a multiple of 4 bytes,",
                                offset);

            } else {
                if (size == wgpu::kWholeSize) {
                    DAWN_CHECK(buffer->GetSize() >= offset);
                    size = buffer->GetSize() - offset;
                }
            }

            mTopLevelBuffers.insert(buffer);

            ClearBufferCmd* cmd = allocator->Allocate<ClearBufferCmd>(Command::ClearBuffer);
            cmd->buffer = buffer;
            cmd->offset = offset;
            cmd->size = size;

            return {};
        },
        "encoding %s.ClearBuffer(%s, %u, %u).", this, buffer, offset, size);
}

void CommandEncoder::APIInjectValidationError(StringView messageIn) {
    std::string_view message = utils::NormalizeMessageString(messageIn);
    mEncodingContext.TryEncode(
        this,
        [&](CommandAllocator*) -> MaybeError {
            return DAWN_MAKE_ERROR(InternalErrorType::Validation, std::string(message));
        },
        "injecting validation error: %s.", message);
}

void CommandEncoder::APIInsertDebugMarker(StringView markerIn) {
    std::string_view marker = utils::NormalizeMessageString(markerIn);
    mEncodingContext.TryEncode(
        this,
        [&](CommandAllocator* allocator) -> MaybeError {
            InsertDebugMarkerCmd* cmd =
                allocator->Allocate<InsertDebugMarkerCmd>(Command::InsertDebugMarker);
            AddNullTerminatedString(allocator, marker, &cmd->length);
            return {};
        },
        "encoding %s.InsertDebugMarker(%s).", this, marker);
}

void CommandEncoder::APIPopDebugGroup() {
    mEncodingContext.TryEncode(
        this,
        [&](CommandAllocator* allocator) -> MaybeError {
            if (GetDevice()->IsValidationEnabled()) {
                DAWN_INVALID_IF(mDebugGroupStackSize == 0,
                                "PopDebugGroup called when no debug groups are currently pushed.");
            }
            allocator->Allocate<PopDebugGroupCmd>(Command::PopDebugGroup);
            mDebugGroupStackSize--;
            mEncodingContext.PopDebugGroupLabel();

            return {};
        },
        "encoding %s.PopDebugGroup().", this);
}

void CommandEncoder::APIPushDebugGroup(StringView groupLabelIn) {
    std::string_view groupLabel = utils::NormalizeMessageString(groupLabelIn);
    mEncodingContext.TryEncode(
        this,
        [&](CommandAllocator* allocator) -> MaybeError {
            PushDebugGroupCmd* cmd =
                allocator->Allocate<PushDebugGroupCmd>(Command::PushDebugGroup);
            const char* label = AddNullTerminatedString(allocator, groupLabel, &cmd->length);

            mDebugGroupStackSize++;
            mEncodingContext.PushDebugGroupLabel(std::string_view(label, cmd->length));

            return {};
        },
        "encoding %s.PushDebugGroup(%s).", this, groupLabel);
}

void CommandEncoder::APIResolveQuerySet(QuerySetBase* querySet,
                                        uint32_t firstQueryUntyped,
                                        uint32_t queryCountUntyped,
                                        BufferBase* destination,
                                        uint64_t destinationOffset) {
    QueryIndex firstQuery{firstQueryUntyped};
    QueryIndex queryCount{queryCountUntyped};

    mEncodingContext.TryEncode(
        this,
        [&](CommandAllocator* allocator) -> MaybeError {
            if (GetDevice()->IsValidationEnabled()) {
                DAWN_TRY(GetDevice()->ValidateObject(querySet));
                DAWN_TRY(GetDevice()->ValidateObject(destination));

                DAWN_TRY(ValidateQuerySetResolve(querySet, firstQuery, queryCount, destination,
                                                 destinationOffset));

                DAWN_TRY(ValidateCanUseAs(destination, wgpu::BufferUsage::QueryResolve));
            }

            TrackUsedQuerySet(querySet);
            mTopLevelBuffers.insert(destination);

            ResolveQuerySetCmd* cmd =
                allocator->Allocate<ResolveQuerySetCmd>(Command::ResolveQuerySet);
            cmd->querySet = querySet;
            cmd->firstQuery = firstQuery;
            cmd->queryCount = queryCount;
            cmd->destination = destination;
            cmd->destinationOffset = destinationOffset;

            if (querySet->GetQueryType() != wgpu::QueryType::Timestamp) {
                return {};
            }

            const bool needsConversion =
                GetDevice()->GetTimestampPeriodInNS() != 1.0f &&
                !GetDevice()->IsToggleEnabled(Toggle::DisableTimestampQueryConversion);
            const bool needsQuantization =
                GetDevice()->IsToggleEnabled(Toggle::TimestampQuantization) &&
                !GetDevice()->AreTimestampsQuantized();
            if (!needsConversion && !needsQuantization) {
                return {};
            }

            auto deviceGuard = GetDevice()->GetGuard();
            return EncodeTimestampsToNanosecondsConversion(this, querySet, firstQuery, queryCount,
                                                           destination, destinationOffset);
        },
        "encoding %s.ResolveQuerySet(%s, %u, %u, %s, %u).", this, querySet, firstQuery, queryCount,
        destination, destinationOffset);
}

void CommandEncoder::APIWriteBuffer(BufferBase* buffer,
                                    uint64_t bufferOffset,
                                    const uint8_t* data,
                                    uint64_t size) {
    mEncodingContext.TryEncode(
        this,
        [&](CommandAllocator* allocator) -> MaybeError {
            if (GetDevice()->IsValidationEnabled()) {
                DAWN_TRY(ValidateWriteBuffer(GetDevice(), buffer, bufferOffset, size));
            }

            WriteBufferCmd* cmd = allocator->Allocate<WriteBufferCmd>(Command::WriteBuffer);
            cmd->buffer = buffer;
            cmd->offset = bufferOffset;
            cmd->size = size;

            uint8_t* inlinedData = allocator->AllocateData<uint8_t>(size);
            DAWN_UNSAFE_TODO(memcpy(inlinedData, data, size));

            mTopLevelBuffers.insert(buffer);

            return {};
        },
        "encoding %s.WriteBuffer(%s, %u, ..., %u).", this, buffer, bufferOffset, size);
}

void CommandEncoder::APIWriteTimestamp(QuerySetBase* querySet, uint32_t queryIndexUntyped) {
    QueryIndex queryIndex{queryIndexUntyped};

    mEncodingContext.TryEncode(
        this,
        [&](CommandAllocator* allocator) -> MaybeError {
            DAWN_INVALID_IF(!GetDevice()->IsToggleEnabled(Toggle::AllowUnsafeAPIs),
                            "writeTimestamp requires enabling toggle allow_unsafe_apis.");

            if (GetDevice()->IsValidationEnabled()) {
                DAWN_TRY(ValidateTimestampQuery(GetDevice(), querySet, queryIndex));
            }

            TrackUsedQuerySet(querySet);

            WriteTimestampCmd* cmd =
                allocator->Allocate<WriteTimestampCmd>(Command::WriteTimestamp);
            cmd->querySet = querySet;
            cmd->queryIndex = queryIndex;

            return {};
        },
        "encoding %s.WriteTimestamp(%s, %u).", this, querySet, queryIndex);
}

CommandBufferBase* CommandEncoder::APIFinish(const CommandBufferDescriptor* descriptor) {
    // This function will create new object, need to lock the Device.
    auto deviceGuard = GetDevice()->GetGuard();

    Ref<CommandBufferBase> commandBuffer;
    if (GetDevice()->ConsumedError(Finish(descriptor), &commandBuffer, "finishing %s.", this)) {
        Ref<CommandBufferBase> errorCommandBuffer =
            CommandBufferBase::MakeError(GetDevice(), descriptor ? descriptor->label : nullptr);
        errorCommandBuffer->SetEncoderLabel(this->GetLabel());
        return ReturnToAPI(std::move(errorCommandBuffer));
    }

    DAWN_CHECK(!IsError());
    return ReturnToAPI(std::move(commandBuffer));
}

ResultOrError<Ref<CommandBufferBase>> CommandEncoder::Finish(
    const CommandBufferDescriptor* descriptor) {
    DeviceBase* device = GetDevice();

    TRACE_EVENT0(device->GetPlatform(), Recording, "CommandEncoder::Finish");

    // Even if mEncodingContext.Finish() validation fails, calling it will mutate the internal
    // state of the encoding context. The internal state is set to finished, and subsequent
    // calls to encode commands will generate errors.
    DAWN_TRY(mEncodingContext.Finish());
    DAWN_TRY(device->ValidateIsAlive());

    if (device->IsValidationEnabled()) {
        DAWN_TRY(ValidateFinish());
    }

    const CommandBufferDescriptor defaultDescriptor = {};
    if (descriptor == nullptr) {
        descriptor = &defaultDescriptor;
    }

    return device->CreateCommandBuffer(this, descriptor);
}

// Implementation of the command buffer validation that can be precomputed before submit
MaybeError CommandEncoder::ValidateFinish() const {
    TRACE_EVENT0(GetDevice()->GetPlatform(), Validation, "CommandEncoder::ValidateFinish");
    DAWN_TRY(GetDevice()->ValidateObject(this));

    for (const RenderPassResourceUsage& passUsage : mEncodingContext.GetRenderPassUsages()) {
        DAWN_TRY_CONTEXT(ValidateSyncScopeResourceUsage(passUsage),
                         "validating render pass usage.");
    }

    for (const ComputePassResourceUsage& passUsage : mEncodingContext.GetComputePassUsages()) {
        for (const SyncScopeResourceUsage& scope : passUsage.dispatchUsages) {
            DAWN_TRY_CONTEXT(ValidateSyncScopeResourceUsage(scope),
                             "validating compute pass usage.");
        }
    }

    DAWN_INVALID_IF(
        mDebugGroupStackSize != 0,
        "PushDebugGroup called %u time(s) without a corresponding PopDebugGroup prior to "
        "calling Finish.",
        mDebugGroupStackSize);

    return {};
}

CommandEncoder::InternalUsageScope CommandEncoder::MakeInternalUsageScope() {
    return InternalUsageScope(this);
}

CommandEncoder::InternalUsageScope::InternalUsageScope(CommandEncoder* encoder)
    : mEncoder(encoder), mUsageValidationMode(mEncoder->mUsageValidationMode) {
    mEncoder->mUsageValidationMode = UsageValidationMode::Internal;
}

CommandEncoder::InternalUsageScope::~InternalUsageScope() {
    mEncoder->mUsageValidationMode = mUsageValidationMode;
}

}  // namespace dawn::native
