// Copyright 2019 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "dawn_native/CommandEncoder.h"

#include "common/BitSetIterator.h"
#include "common/Math.h"
#include "dawn_native/BindGroup.h"
#include "dawn_native/Buffer.h"
#include "dawn_native/CommandBuffer.h"
#include "dawn_native/CommandBufferStateTracker.h"
#include "dawn_native/CommandValidation.h"
#include "dawn_native/Commands.h"
#include "dawn_native/ComputePassEncoder.h"
#include "dawn_native/Device.h"
#include "dawn_native/ErrorData.h"
#include "dawn_native/ObjectType_autogen.h"
#include "dawn_native/QueryHelper.h"
#include "dawn_native/QuerySet.h"
#include "dawn_native/Queue.h"
#include "dawn_native/RenderPassEncoder.h"
#include "dawn_native/RenderPipeline.h"
#include "dawn_native/ValidationUtils_autogen.h"
#include "dawn_platform/DawnPlatform.h"
#include "dawn_platform/tracing/TraceEvent.h"

#include <cmath>
#include <map>

namespace dawn_native {

    namespace {

        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 TextureDataLayout& 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 ValidateTextureDepthStencilToBufferCopyRestrictions(
            const ImageCopyTexture& src) {
            Aspect aspectUsed;
            DAWN_TRY_ASSIGN(aspectUsed, SingleAspectUsedByImageCopyTexture(src));
            if (aspectUsed == Aspect::Depth) {
                switch (src.texture->GetFormat().format) {
                    case wgpu::TextureFormat::Depth24Plus:
                    case wgpu::TextureFormat::Depth24PlusStencil8:
                    case wgpu::TextureFormat::Depth24UnormStencil8:
                        return DAWN_FORMAT_VALIDATION_ERROR(
                            "The depth aspect of %s format %s cannot be selected in a texture to "
                            "buffer copy.",
                            src.texture, src.texture->GetFormat().format);
                    case wgpu::TextureFormat::Depth32Float:
                    case wgpu::TextureFormat::Depth16Unorm:
                    case wgpu::TextureFormat::Depth32FloatStencil8:
                        break;

                    default:
                        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 ValidateOrSetAttachmentSize(const TextureViewBase* attachment,
                                               uint32_t* width,
                                               uint32_t* height) {
            const Extent3D& attachmentSize =
                attachment->GetTexture()->GetMipLevelVirtualSize(attachment->GetBaseMipLevel());

            if (*width == 0) {
                DAWN_ASSERT(*height == 0);
                *width = attachmentSize.width;
                *height = attachmentSize.height;
                DAWN_ASSERT(*width != 0 && *height != 0);
            } else {
                DAWN_INVALID_IF(
                    *width != attachmentSize.width || *height != attachmentSize.height,
                    "Attachment %s size (width: %u, height: %u) does not match the size of the "
                    "other attachments (width: %u, height: %u).",
                    attachment, attachmentSize.width, attachmentSize.height, *width, *height);
            }

            return {};
        }

        MaybeError ValidateOrSetColorAttachmentSampleCount(const TextureViewBase* colorAttachment,
                                                           uint32_t* sampleCount) {
            if (*sampleCount == 0) {
                *sampleCount = colorAttachment->GetTexture()->GetSampleCount();
                DAWN_ASSERT(*sampleCount != 0);
            } else {
                DAWN_INVALID_IF(
                    *sampleCount != colorAttachment->GetTexture()->GetSampleCount(),
                    "Color attachment %s sample count (%u) does not match the sample count of the "
                    "other attachments (%u).",
                    colorAttachment, colorAttachment->GetTexture()->GetSampleCount(), *sampleCount);
            }

            return {};
        }

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

            const TextureViewBase* resolveTarget = colorAttachment.resolveTarget;
            const TextureViewBase* attachment = colorAttachment.view;
            DAWN_TRY(device->ValidateObject(colorAttachment.resolveTarget));
            DAWN_TRY(ValidateCanUseAs(colorAttachment.resolveTarget->GetTexture(),
                                      wgpu::TextureUsage::RenderAttachment));

            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->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());

            const Extent3D& colorTextureSize =
                attachment->GetTexture()->GetMipLevelVirtualSize(attachment->GetBaseMipLevel());
            const Extent3D& resolveTextureSize =
                resolveTarget->GetTexture()->GetMipLevelVirtualSize(
                    resolveTarget->GetBaseMipLevel());
            DAWN_INVALID_IF(
                colorTextureSize.width != resolveTextureSize.width ||
                    colorTextureSize.height != resolveTextureSize.height,
                "The Resolve target %s size (width: %u, height: %u) does not match the color "
                "attachment %s size (width: %u, height: %u).",
                resolveTarget, resolveTextureSize.width, resolveTextureSize.height, attachment,
                colorTextureSize.width, colorTextureSize.height);

            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);

            return {};
        }

        MaybeError ValidateRenderPassColorAttachment(
            DeviceBase* device,
            const RenderPassColorAttachment& colorAttachment,
            uint32_t* width,
            uint32_t* height,
            uint32_t* sampleCount) {
            TextureViewBase* attachment = colorAttachment.view;
            DAWN_TRY(device->ValidateObject(attachment));
            DAWN_TRY(
                ValidateCanUseAs(attachment->GetTexture(), wgpu::TextureUsage::RenderAttachment));

            DAWN_INVALID_IF(!(attachment->GetAspects() & Aspect::Color) ||
                                !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));

            if (colorAttachment.loadOp == wgpu::LoadOp::Clear) {
                DAWN_INVALID_IF(std::isnan(colorAttachment.clearColor.r) ||
                                    std::isnan(colorAttachment.clearColor.g) ||
                                    std::isnan(colorAttachment.clearColor.b) ||
                                    std::isnan(colorAttachment.clearColor.a),
                                "Color clear value (%s) contain a NaN.",
                                &colorAttachment.clearColor);
            }

            DAWN_TRY(ValidateOrSetColorAttachmentSampleCount(attachment, sampleCount));

            DAWN_TRY(ValidateResolveTarget(device, colorAttachment));

            DAWN_TRY(ValidateAttachmentArrayLayersAndLevelCount(attachment));
            DAWN_TRY(ValidateOrSetAttachmentSize(attachment, width, height));

            return {};
        }

        MaybeError ValidateRenderPassDepthStencilAttachment(
            DeviceBase* device,
            const RenderPassDepthStencilAttachment* depthStencilAttachment,
            uint32_t* width,
            uint32_t* height,
            uint32_t* sampleCount) {
            DAWN_ASSERT(depthStencilAttachment != nullptr);

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

            const Format& format = attachment->GetFormat();
            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);

            DAWN_INVALID_IF(attachment->GetAspects() != format.aspects,
                            "The depth stencil attachment %s must encompass all aspects.",
                            attachment);

            DAWN_TRY(ValidateLoadOp(depthStencilAttachment->depthLoadOp));
            DAWN_TRY(ValidateLoadOp(depthStencilAttachment->stencilLoadOp));
            DAWN_TRY(ValidateStoreOp(depthStencilAttachment->depthStoreOp));
            DAWN_TRY(ValidateStoreOp(depthStencilAttachment->stencilStoreOp));

            DAWN_INVALID_IF(
                attachment->GetAspects() == (Aspect::Depth | Aspect::Stencil) &&
                    depthStencilAttachment->depthReadOnly !=
                        depthStencilAttachment->stencilReadOnly,
                "depthReadOnly (%u) and stencilReadOnly (%u) must be the same when texture aspect "
                "is 'all'.",
                depthStencilAttachment->depthReadOnly, depthStencilAttachment->stencilReadOnly);

            DAWN_INVALID_IF(
                depthStencilAttachment->depthReadOnly &&
                    (depthStencilAttachment->depthLoadOp != wgpu::LoadOp::Load ||
                     depthStencilAttachment->depthStoreOp != wgpu::StoreOp::Store),
                "depthLoadOp (%s) is not %s or depthStoreOp (%s) is not %s when depthReadOnly "
                "is true.",
                depthStencilAttachment->depthLoadOp, wgpu::LoadOp::Load,
                depthStencilAttachment->depthStoreOp, wgpu::StoreOp::Store);

            DAWN_INVALID_IF(depthStencilAttachment->stencilReadOnly &&
                                (depthStencilAttachment->stencilLoadOp != wgpu::LoadOp::Load ||
                                 depthStencilAttachment->stencilStoreOp != wgpu::StoreOp::Store),
                            "stencilLoadOp (%s) is not %s or stencilStoreOp (%s) is not %s when "
                            "stencilReadOnly is true.",
                            depthStencilAttachment->stencilLoadOp, wgpu::LoadOp::Load,
                            depthStencilAttachment->stencilStoreOp, wgpu::StoreOp::Store);

            DAWN_INVALID_IF(depthStencilAttachment->depthLoadOp == wgpu::LoadOp::Clear &&
                                std::isnan(depthStencilAttachment->clearDepth),
                            "Depth clear value is NaN.");

            // *sampleCount == 0 must only happen when there is no color attachment. In that case we
            // do not need to validate the sample count of the depth stencil attachment.
            const uint32_t depthStencilSampleCount = attachment->GetTexture()->GetSampleCount();
            if (*sampleCount != 0) {
                DAWN_INVALID_IF(
                    depthStencilSampleCount != *sampleCount,
                    "The depth stencil attachment %s sample count (%u) does not match the sample "
                    "count of the other attachments (%u).",
                    attachment, depthStencilSampleCount, *sampleCount);
            } else {
                *sampleCount = depthStencilSampleCount;
            }

            DAWN_TRY(ValidateAttachmentArrayLayersAndLevelCount(attachment));
            DAWN_TRY(ValidateOrSetAttachmentSize(attachment, width, height));

            return {};
        }

        MaybeError ValidateRenderPassDescriptor(DeviceBase* device,
                                                const RenderPassDescriptor* descriptor,
                                                uint32_t* width,
                                                uint32_t* height,
                                                uint32_t* sampleCount) {
            DAWN_INVALID_IF(
                descriptor->colorAttachmentCount > kMaxColorAttachments,
                "Color attachment count (%u) exceeds the maximum number of color attachments (%u).",
                descriptor->colorAttachmentCount, kMaxColorAttachments);

            for (uint32_t i = 0; i < descriptor->colorAttachmentCount; ++i) {
                DAWN_TRY_CONTEXT(
                    ValidateRenderPassColorAttachment(device, descriptor->colorAttachments[i],
                                                      width, height, sampleCount),
                    "validating colorAttachments[%u].", i);
            }

            if (descriptor->depthStencilAttachment != nullptr) {
                DAWN_TRY_CONTEXT(
                    ValidateRenderPassDepthStencilAttachment(
                        device, descriptor->depthStencilAttachment, width, height, sampleCount),
                    "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);
            }

            DAWN_INVALID_IF(descriptor->colorAttachmentCount == 0 &&
                                descriptor->depthStencilAttachment == nullptr,
                            "Render pass has no attachments.");

            return {};
        }

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

        MaybeError ValidateQuerySetResolve(const QuerySetBase* querySet,
                                           uint32_t firstQuery,
                                           uint32_t 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 % 256 != 0,
                            "The destination buffer %s offset (%u) is not a multiple of 256.",
                            destination, destinationOffset);

            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,
                                                           uint32_t firstQuery,
                                                           uint32_t queryCount,
                                                           BufferBase* destination,
                                                           uint64_t destinationOffset) {
            DeviceBase* device = encoder->GetDevice();

            // The availability got from query set is a reference to vector<bool>, need to covert
            // bool to uint32_t due to a user input in pipeline must not contain a bool type in
            // WGSL.
            std::vector<uint32_t> availability{querySet->GetQueryAvailability().begin(),
                                               querySet->GetQueryAvailability().end()};

            // Timestamp availability storage buffer
            BufferDescriptor availabilityDesc = {};
            availabilityDesc.usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopyDst;
            availabilityDesc.size = querySet->GetQueryCount() * sizeof(uint32_t);
            Ref<BufferBase> availabilityBuffer;
            DAWN_TRY_ASSIGN(availabilityBuffer, device->CreateBuffer(&availabilityDesc));

            DAWN_TRY(device->GetQueue()->WriteBuffer(availabilityBuffer.Get(), 0,
                                                     availability.data(),
                                                     availability.size() * sizeof(uint32_t)));

            // Timestamp params uniform buffer
            TimestampParams params = {firstQuery, queryCount,
                                      static_cast<uint32_t>(destinationOffset),
                                      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, &params, sizeof(params)));

            return EncodeConvertTimestampsToNanoseconds(
                encoder, destination, availabilityBuffer.Get(), paramsBuffer.Get());
        }

        bool IsReadOnlyDepthStencilAttachment(
            const RenderPassDepthStencilAttachment* depthStencilAttachment) {
            DAWN_ASSERT(depthStencilAttachment != nullptr);
            Aspect aspects = depthStencilAttachment->view->GetAspects();
            DAWN_ASSERT(IsSubset(aspects, Aspect::Depth | Aspect::Stencil));

            if ((aspects & Aspect::Depth) && !depthStencilAttachment->depthReadOnly) {
                return false;
            }
            if (aspects & Aspect::Stencil && !depthStencilAttachment->stencilReadOnly) {
                return false;
            }
            return true;
        }

    }  // namespace

    CommandEncoder::CommandEncoder(DeviceBase* device, const CommandEncoderDescriptor* descriptor)
        : ApiObjectBase(device, descriptor->label), mEncodingContext(device, this) {
        TrackInDevice();
    }

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

    void CommandEncoder::DestroyImpl() {
        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);
    }

    void CommandEncoder::TrackQueryAvailability(QuerySetBase* querySet, uint32_t queryIndex) {
        DAWN_ASSERT(querySet != nullptr);

        if (GetDevice()->IsValidationEnabled()) {
            TrackUsedQuerySet(querySet);
        }

        // Set the query at queryIndex to available for resolving in query set.
        querySet->SetQueryAvailability(queryIndex, true);
    }

    // Implementation of the API's command recording methods

    ComputePassEncoder* CommandEncoder::APIBeginComputePass(
        const ComputePassDescriptor* descriptor) {
        DeviceBase* device = GetDevice();

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

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

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

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

            ComputePassEncoder* passEncoder =
                new ComputePassEncoder(device, descriptor, this, &mEncodingContext);
            mEncodingContext.EnterPass(passEncoder);
            return passEncoder;
        }

        return ComputePassEncoder::MakeError(device, this, &mEncodingContext);
    }

    RenderPassEncoder* CommandEncoder::APIBeginRenderPass(const RenderPassDescriptor* descriptor) {
        DeviceBase* device = GetDevice();

        RenderPassResourceUsageTracker usageTracker;

        uint32_t width = 0;
        uint32_t height = 0;
        bool depthReadOnly = false;
        bool stencilReadOnly = false;
        Ref<AttachmentState> attachmentState;
        bool success = mEncodingContext.TryEncode(
            this,
            [&](CommandAllocator* allocator) -> MaybeError {
                uint32_t sampleCount = 0;

                DAWN_TRY(ValidateRenderPassDescriptor(device, descriptor, &width, &height,
                                                      &sampleCount));

                ASSERT(width > 0 && height > 0 && sampleCount > 0);

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

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

                for (ColorAttachmentIndex index :
                     IterateBitSet(cmd->attachmentState->GetColorAttachmentsMask())) {
                    uint8_t i = static_cast<uint8_t>(index);
                    TextureViewBase* view = descriptor->colorAttachments[i].view;
                    TextureViewBase* resolveTarget = descriptor->colorAttachments[i].resolveTarget;

                    cmd->colorAttachments[index].view = view;
                    cmd->colorAttachments[index].resolveTarget = resolveTarget;
                    cmd->colorAttachments[index].loadOp = descriptor->colorAttachments[i].loadOp;
                    cmd->colorAttachments[index].storeOp = descriptor->colorAttachments[i].storeOp;
                    cmd->colorAttachments[index].clearColor =
                        descriptor->colorAttachments[i].clearColor;

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

                    if (resolveTarget != nullptr) {
                        usageTracker.TextureViewUsedAs(resolveTarget,
                                                       wgpu::TextureUsage::RenderAttachment);
                    }
                }

                if (cmd->attachmentState->HasDepthStencilAttachment()) {
                    TextureViewBase* view = descriptor->depthStencilAttachment->view;

                    cmd->depthStencilAttachment.view = view;
                    cmd->depthStencilAttachment.clearDepth =
                        descriptor->depthStencilAttachment->clearDepth;
                    cmd->depthStencilAttachment.clearStencil =
                        descriptor->depthStencilAttachment->clearStencil;
                    cmd->depthStencilAttachment.depthLoadOp =
                        descriptor->depthStencilAttachment->depthLoadOp;
                    cmd->depthStencilAttachment.depthStoreOp =
                        descriptor->depthStencilAttachment->depthStoreOp;
                    cmd->depthStencilAttachment.stencilLoadOp =
                        descriptor->depthStencilAttachment->stencilLoadOp;
                    cmd->depthStencilAttachment.stencilStoreOp =
                        descriptor->depthStencilAttachment->stencilStoreOp;
                    cmd->depthStencilAttachment.depthReadOnly =
                        descriptor->depthStencilAttachment->depthReadOnly;
                    cmd->depthStencilAttachment.stencilReadOnly =
                        descriptor->depthStencilAttachment->stencilReadOnly;

                    if (IsReadOnlyDepthStencilAttachment(descriptor->depthStencilAttachment)) {
                        // TODO(dawn:485): Readonly depth/stencil attachment is not fully
                        // implemented. Disallow it as unsafe until the implementaion is completed.
                        DAWN_INVALID_IF(
                            device->IsToggleEnabled(Toggle::DisallowUnsafeAPIs),
                            "Readonly depth/stencil attachment is disallowed because it's not "
                            "fully implemented");

                        usageTracker.TextureViewUsedAs(view, kReadOnlyRenderAttachment);
                    } else {
                        usageTracker.TextureViewUsedAs(view, wgpu::TextureUsage::RenderAttachment);
                    }

                    depthReadOnly = descriptor->depthStencilAttachment->depthReadOnly;
                    stencilReadOnly = descriptor->depthStencilAttachment->stencilReadOnly;
                }

                cmd->width = width;
                cmd->height = height;

                cmd->occlusionQuerySet = descriptor->occlusionQuerySet;

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

        if (success) {
            RenderPassEncoder* passEncoder = new RenderPassEncoder(
                device, descriptor, this, &mEncodingContext, std::move(usageTracker),
                std::move(attachmentState), descriptor->occlusionQuerySet, width, height,
                depthReadOnly, stencilReadOnly);
            mEncodingContext.EnterPass(passEncoder);
            return passEncoder;
        }

        return RenderPassEncoder::MakeError(device, this, &mEncodingContext);
    }

    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);
    }

    void CommandEncoder::APICopyBufferToTexture(const ImageCopyBuffer* source,
                                                const ImageCopyTexture* destination,
                                                const Extent3D* copySize) {
        mEncodingContext.TryEncode(
            this,
            [&](CommandAllocator* allocator) -> MaybeError {
                if (GetDevice()->IsValidationEnabled()) {
                    DAWN_TRY(ValidateImageCopyBuffer(GetDevice(), *source));
                    DAWN_TRY_CONTEXT(ValidateCanUseAs(source->buffer, wgpu::BufferUsage::CopySrc),
                                     "validating source %s usage.", source->buffer);

                    DAWN_TRY(ValidateImageCopyTexture(GetDevice(), *destination, *copySize));
                    DAWN_TRY_CONTEXT(
                        ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst),
                        "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 TexelBlockInfo& blockInfo =
                    destination->texture->GetFormat().GetAspectInfo(destination->aspect).block;
                if (GetDevice()->IsValidationEnabled()) {
                    DAWN_TRY(ValidateLinearTextureCopyOffset(
                        source->layout, blockInfo,
                        destination->texture->GetFormat().HasDepthOrStencil()));
                    DAWN_TRY(ValidateLinearTextureData(source->layout, source->buffer->GetSize(),
                                                       blockInfo, *copySize));

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

                TextureDataLayout srcLayout = source->layout;
                ApplyDefaultTextureDataLayoutOptions(&srcLayout, blockInfo, *copySize);

                CopyBufferToTextureCmd* copy =
                    allocator->Allocate<CopyBufferToTextureCmd>(Command::CopyBufferToTexture);
                copy->source.buffer = source->buffer;
                copy->source.offset = srcLayout.offset;
                copy->source.bytesPerRow = srcLayout.bytesPerRow;
                copy->source.rowsPerImage = srcLayout.rowsPerImage;
                copy->destination.texture = destination->texture;
                copy->destination.origin = destination->origin;
                copy->destination.mipLevel = destination->mipLevel;
                copy->destination.aspect =
                    ConvertAspect(destination->texture->GetFormat(), destination->aspect);
                copy->copySize = *copySize;

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

    void CommandEncoder::APICopyTextureToBuffer(const ImageCopyTexture* source,
                                                const ImageCopyBuffer* destination,
                                                const Extent3D* copySize) {
        mEncodingContext.TryEncode(
            this,
            [&](CommandAllocator* allocator) -> MaybeError {
                if (GetDevice()->IsValidationEnabled()) {
                    DAWN_TRY(ValidateImageCopyTexture(GetDevice(), *source, *copySize));
                    DAWN_TRY_CONTEXT(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc),
                                     "validating source %s usage.", source->texture);
                    DAWN_TRY(ValidateTextureSampleCountInBufferCopyCommands(source->texture));
                    DAWN_TRY(ValidateTextureDepthStencilToBufferCopyRestrictions(*source));

                    DAWN_TRY(ValidateImageCopyBuffer(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));
                }
                const TexelBlockInfo& blockInfo =
                    source->texture->GetFormat().GetAspectInfo(source->aspect).block;
                if (GetDevice()->IsValidationEnabled()) {
                    DAWN_TRY(ValidateLinearTextureCopyOffset(
                        destination->layout, blockInfo,
                        source->texture->GetFormat().HasDepthOrStencil()));
                    DAWN_TRY(ValidateLinearTextureData(
                        destination->layout, destination->buffer->GetSize(), blockInfo, *copySize));

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

                TextureDataLayout dstLayout = destination->layout;
                ApplyDefaultTextureDataLayoutOptions(&dstLayout, blockInfo, *copySize);

                CopyTextureToBufferCmd* copy =
                    allocator->Allocate<CopyTextureToBufferCmd>(Command::CopyTextureToBuffer);
                copy->source.texture = source->texture;
                copy->source.origin = source->origin;
                copy->source.mipLevel = source->mipLevel;
                copy->source.aspect = ConvertAspect(source->texture->GetFormat(), source->aspect);
                copy->destination.buffer = destination->buffer;
                copy->destination.offset = dstLayout.offset;
                copy->destination.bytesPerRow = dstLayout.bytesPerRow;
                copy->destination.rowsPerImage = dstLayout.rowsPerImage;
                copy->copySize = *copySize;

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

    void CommandEncoder::APICopyTextureToTexture(const ImageCopyTexture* source,
                                                 const ImageCopyTexture* destination,
                                                 const Extent3D* copySize) {
        APICopyTextureToTextureHelper<false>(source, destination, copySize);
    }

    void CommandEncoder::APICopyTextureToTextureInternal(const ImageCopyTexture* source,
                                                         const ImageCopyTexture* destination,
                                                         const Extent3D* copySize) {
        APICopyTextureToTextureHelper<true>(source, destination, copySize);
    }

    template <bool Internal>
    void CommandEncoder::APICopyTextureToTextureHelper(const ImageCopyTexture* source,
                                                       const ImageCopyTexture* destination,
                                                       const Extent3D* copySize) {
        mEncodingContext.TryEncode(
            this,
            [&](CommandAllocator* allocator) -> MaybeError {
                if (GetDevice()->IsValidationEnabled()) {
                    DAWN_TRY(GetDevice()->ValidateObject(source->texture));
                    DAWN_TRY(GetDevice()->ValidateObject(destination->texture));

                    DAWN_TRY_CONTEXT(ValidateImageCopyTexture(GetDevice(), *source, *copySize),
                                     "validating source %s.", source->texture);
                    DAWN_TRY_CONTEXT(ValidateImageCopyTexture(GetDevice(), *destination, *copySize),
                                     "validating destination %s.", destination->texture);

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

                    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);

                    // For internal usages (CopyToCopyInternal) we don't care if the user has added
                    // CopySrc as a usage for this texture, but we will always add it internally.
                    if (Internal) {
                        DAWN_TRY(
                            ValidateInternalCanUseAs(source->texture, wgpu::TextureUsage::CopySrc));
                        DAWN_TRY(ValidateInternalCanUseAs(destination->texture,
                                                          wgpu::TextureUsage::CopyDst));
                    } else {
                        DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc));
                        DAWN_TRY(
                            ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst));
                    }

                    mTopLevelTextures.insert(source->texture);
                    mTopLevelTextures.insert(destination->texture);
                }

                CopyTextureToTextureCmd* copy =
                    allocator->Allocate<CopyTextureToTextureCmd>(Command::CopyTextureToTexture);
                copy->source.texture = source->texture;
                copy->source.origin = source->origin;
                copy->source.mipLevel = source->mipLevel;
                copy->source.aspect = ConvertAspect(source->texture->GetFormat(), source->aspect);
                copy->destination.texture = destination->texture;
                copy->destination.origin = destination->origin;
                copy->destination.mipLevel = destination->mipLevel;
                copy->destination.aspect =
                    ConvertAspect(destination->texture->GetFormat(), destination->aspect);
                copy->copySize = *copySize;

                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);

                    mTopLevelBuffers.insert(buffer);
                } else {
                    if (size == wgpu::kWholeSize) {
                        DAWN_ASSERT(buffer->GetSize() >= offset);
                        size = buffer->GetSize() - offset;
                    }
                }

                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(const char* message) {
        if (mEncodingContext.CheckCurrentEncoder(this)) {
            mEncodingContext.HandleError(DAWN_VALIDATION_ERROR(message));
        }
    }

    void CommandEncoder::APIInsertDebugMarker(const char* groupLabel) {
        mEncodingContext.TryEncode(
            this,
            [&](CommandAllocator* allocator) -> MaybeError {
                InsertDebugMarkerCmd* cmd =
                    allocator->Allocate<InsertDebugMarkerCmd>(Command::InsertDebugMarker);
                cmd->length = strlen(groupLabel);

                char* label = allocator->AllocateData<char>(cmd->length + 1);
                memcpy(label, groupLabel, cmd->length + 1);

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

    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(const char* groupLabel) {
        mEncodingContext.TryEncode(
            this,
            [&](CommandAllocator* allocator) -> MaybeError {
                PushDebugGroupCmd* cmd =
                    allocator->Allocate<PushDebugGroupCmd>(Command::PushDebugGroup);
                cmd->length = strlen(groupLabel);

                char* label = allocator->AllocateData<char>(cmd->length + 1);
                memcpy(label, groupLabel, cmd->length + 1);

                mDebugGroupStackSize++;
                mEncodingContext.PushDebugGroupLabel(groupLabel);

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

    void CommandEncoder::APIResolveQuerySet(QuerySetBase* querySet,
                                            uint32_t firstQuery,
                                            uint32_t queryCount,
                                            BufferBase* destination,
                                            uint64_t destinationOffset) {
        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;

                // Encode internal compute pipeline for timestamp query
                if (querySet->GetQueryType() == wgpu::QueryType::Timestamp) {
                    DAWN_TRY(EncodeTimestampsToNanosecondsConversion(
                        this, querySet, firstQuery, queryCount, destination, destinationOffset));
                }

                return {};
            },
            "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);
                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 queryIndex) {
        mEncodingContext.TryEncode(
            this,
            [&](CommandAllocator* allocator) -> MaybeError {
                if (GetDevice()->IsValidationEnabled()) {
                    DAWN_TRY(GetDevice()->ValidateObject(querySet));
                    DAWN_TRY(ValidateTimestampQuery(querySet, queryIndex));
                }

                TrackQueryAvailability(querySet, queryIndex);

                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) {
        Ref<CommandBufferBase> commandBuffer;
        if (GetDevice()->ConsumedError(FinishInternal(descriptor), &commandBuffer)) {
            return CommandBufferBase::MakeError(GetDevice());
        }
        ASSERT(!IsError());
        return commandBuffer.Detach();
    }

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

        // 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 {};
    }

}  // namespace dawn_native
