// Copyright 2017 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/metal/CommandBufferMTL.h"

#include "dawn_native/BindGroupTracker.h"
#include "dawn_native/CommandEncoder.h"
#include "dawn_native/Commands.h"
#include "dawn_native/ExternalTexture.h"
#include "dawn_native/RenderBundle.h"
#include "dawn_native/metal/BindGroupMTL.h"
#include "dawn_native/metal/BufferMTL.h"
#include "dawn_native/metal/ComputePipelineMTL.h"
#include "dawn_native/metal/DeviceMTL.h"
#include "dawn_native/metal/PipelineLayoutMTL.h"
#include "dawn_native/metal/QuerySetMTL.h"
#include "dawn_native/metal/RenderPipelineMTL.h"
#include "dawn_native/metal/SamplerMTL.h"
#include "dawn_native/metal/TextureMTL.h"
#include "dawn_native/metal/UtilsMetal.h"

#include <tint/tint.h>

namespace dawn_native { namespace metal {

    namespace {

        // Allows this file to use MTLStoreActionStoreAndMultismapleResolve because the logic is
        // first to compute what the "best" Metal render pass descriptor is, then fix it up if we
        // are not on macOS 10.12 (i.e. the EmulateStoreAndMSAAResolve toggle is on).
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability"
        constexpr MTLStoreAction kMTLStoreActionStoreAndMultisampleResolve =
            MTLStoreActionStoreAndMultisampleResolve;
#pragma clang diagnostic pop

        MTLIndexType MTLIndexFormat(wgpu::IndexFormat format) {
            switch (format) {
                case wgpu::IndexFormat::Uint16:
                    return MTLIndexTypeUInt16;
                case wgpu::IndexFormat::Uint32:
                    return MTLIndexTypeUInt32;
                case wgpu::IndexFormat::Undefined:
                    UNREACHABLE();
            }
        }

        NSRef<MTLRenderPassDescriptor> CreateMTLRenderPassDescriptor(
            BeginRenderPassCmd* renderPass) {
            // Note that this creates a descriptor that's autoreleased so we don't use AcquireNSRef
            NSRef<MTLRenderPassDescriptor> descriptorRef =
                [MTLRenderPassDescriptor renderPassDescriptor];
            MTLRenderPassDescriptor* descriptor = descriptorRef.Get();

            for (ColorAttachmentIndex attachment :
                 IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
                uint8_t i = static_cast<uint8_t>(attachment);
                auto& attachmentInfo = renderPass->colorAttachments[attachment];

                switch (attachmentInfo.loadOp) {
                    case wgpu::LoadOp::Clear:
                        descriptor.colorAttachments[i].loadAction = MTLLoadActionClear;
                        descriptor.colorAttachments[i].clearColor = MTLClearColorMake(
                            attachmentInfo.clearColor.r, attachmentInfo.clearColor.g,
                            attachmentInfo.clearColor.b, attachmentInfo.clearColor.a);
                        break;

                    case wgpu::LoadOp::Load:
                        descriptor.colorAttachments[i].loadAction = MTLLoadActionLoad;
                        break;
                }

                descriptor.colorAttachments[i].texture =
                    ToBackend(attachmentInfo.view->GetTexture())->GetMTLTexture();
                descriptor.colorAttachments[i].level = attachmentInfo.view->GetBaseMipLevel();
                descriptor.colorAttachments[i].slice = attachmentInfo.view->GetBaseArrayLayer();

                bool hasResolveTarget = attachmentInfo.resolveTarget != nullptr;
                if (hasResolveTarget) {
                    descriptor.colorAttachments[i].resolveTexture =
                        ToBackend(attachmentInfo.resolveTarget->GetTexture())->GetMTLTexture();
                    descriptor.colorAttachments[i].resolveLevel =
                        attachmentInfo.resolveTarget->GetBaseMipLevel();
                    descriptor.colorAttachments[i].resolveSlice =
                        attachmentInfo.resolveTarget->GetBaseArrayLayer();

                    switch (attachmentInfo.storeOp) {
                        case wgpu::StoreOp::Store:
                            descriptor.colorAttachments[i].storeAction =
                                kMTLStoreActionStoreAndMultisampleResolve;
                            break;
                        case wgpu::StoreOp::Discard:
                        case wgpu::StoreOp::Clear:
                            descriptor.colorAttachments[i].storeAction =
                                MTLStoreActionMultisampleResolve;
                            break;
                    }
                } else {
                    switch (attachmentInfo.storeOp) {
                        case wgpu::StoreOp::Store:
                            descriptor.colorAttachments[i].storeAction = MTLStoreActionStore;
                            break;
                        case wgpu::StoreOp::Discard:
                        case wgpu::StoreOp::Clear:
                            descriptor.colorAttachments[i].storeAction = MTLStoreActionDontCare;
                            break;
                    }
                }
            }

            if (renderPass->attachmentState->HasDepthStencilAttachment()) {
                auto& attachmentInfo = renderPass->depthStencilAttachment;

                id<MTLTexture> texture =
                    ToBackend(attachmentInfo.view->GetTexture())->GetMTLTexture();
                const Format& format = attachmentInfo.view->GetTexture()->GetFormat();

                if (format.HasDepth()) {
                    descriptor.depthAttachment.texture = texture;
                    descriptor.depthAttachment.level = attachmentInfo.view->GetBaseMipLevel();
                    descriptor.depthAttachment.slice = attachmentInfo.view->GetBaseArrayLayer();

                    switch (attachmentInfo.depthStoreOp) {
                        case wgpu::StoreOp::Store:
                            descriptor.depthAttachment.storeAction = MTLStoreActionStore;
                            break;

                        case wgpu::StoreOp::Discard:
                        case wgpu::StoreOp::Clear:
                            descriptor.depthAttachment.storeAction = MTLStoreActionDontCare;
                            break;
                    }

                    switch (attachmentInfo.depthLoadOp) {
                        case wgpu::LoadOp::Clear:
                            descriptor.depthAttachment.loadAction = MTLLoadActionClear;
                            descriptor.depthAttachment.clearDepth = attachmentInfo.clearDepth;
                            break;

                        case wgpu::LoadOp::Load:
                            descriptor.depthAttachment.loadAction = MTLLoadActionLoad;
                            break;
                    }
                }

                if (format.HasStencil()) {
                    descriptor.stencilAttachment.texture = texture;
                    descriptor.stencilAttachment.level = attachmentInfo.view->GetBaseMipLevel();
                    descriptor.stencilAttachment.slice = attachmentInfo.view->GetBaseArrayLayer();

                    switch (attachmentInfo.stencilStoreOp) {
                        case wgpu::StoreOp::Store:
                            descriptor.stencilAttachment.storeAction = MTLStoreActionStore;
                            break;

                        case wgpu::StoreOp::Discard:
                        case wgpu::StoreOp::Clear:
                            descriptor.stencilAttachment.storeAction = MTLStoreActionDontCare;
                            break;
                    }

                    switch (attachmentInfo.stencilLoadOp) {
                        case wgpu::LoadOp::Clear:
                            descriptor.stencilAttachment.loadAction = MTLLoadActionClear;
                            descriptor.stencilAttachment.clearStencil = attachmentInfo.clearStencil;
                            break;

                        case wgpu::LoadOp::Load:
                            descriptor.stencilAttachment.loadAction = MTLLoadActionLoad;
                            break;
                    }
                }
            }

            if (renderPass->occlusionQuerySet.Get() != nullptr) {
                descriptor.visibilityResultBuffer =
                    ToBackend(renderPass->occlusionQuerySet.Get())->GetVisibilityBuffer();
            }

            return descriptorRef;
        }

        // Helper function for Toggle EmulateStoreAndMSAAResolve
        void ResolveInAnotherRenderPass(
            CommandRecordingContext* commandContext,
            const MTLRenderPassDescriptor* mtlRenderPass,
            const std::array<id<MTLTexture>, kMaxColorAttachments>& resolveTextures) {
            // Note that this creates a descriptor that's autoreleased so we don't use AcquireNSRef
            NSRef<MTLRenderPassDescriptor> mtlRenderPassForResolveRef =
                [MTLRenderPassDescriptor renderPassDescriptor];
            MTLRenderPassDescriptor* mtlRenderPassForResolve = mtlRenderPassForResolveRef.Get();

            for (uint32_t i = 0; i < kMaxColorAttachments; ++i) {
                if (resolveTextures[i] == nullptr) {
                    continue;
                }

                mtlRenderPassForResolve.colorAttachments[i].texture =
                    mtlRenderPass.colorAttachments[i].texture;
                mtlRenderPassForResolve.colorAttachments[i].loadAction = MTLLoadActionLoad;
                mtlRenderPassForResolve.colorAttachments[i].storeAction =
                    MTLStoreActionMultisampleResolve;
                mtlRenderPassForResolve.colorAttachments[i].resolveTexture = resolveTextures[i];
                mtlRenderPassForResolve.colorAttachments[i].resolveLevel =
                    mtlRenderPass.colorAttachments[i].resolveLevel;
                mtlRenderPassForResolve.colorAttachments[i].resolveSlice =
                    mtlRenderPass.colorAttachments[i].resolveSlice;
            }

            commandContext->BeginRender(mtlRenderPassForResolve);
            commandContext->EndRender();
        }

        // Helper functions for Toggle AlwaysResolveIntoZeroLevelAndLayer
        ResultOrError<NSPRef<id<MTLTexture>>> CreateResolveTextureForWorkaround(
            Device* device,
            MTLPixelFormat mtlFormat,
            uint32_t width,
            uint32_t height) {
            NSRef<MTLTextureDescriptor> mtlDescRef = AcquireNSRef([MTLTextureDescriptor new]);
            MTLTextureDescriptor* mtlDesc = mtlDescRef.Get();

            mtlDesc.textureType = MTLTextureType2D;
            mtlDesc.usage = MTLTextureUsageRenderTarget;
            mtlDesc.pixelFormat = mtlFormat;
            mtlDesc.width = width;
            mtlDesc.height = height;
            mtlDesc.depth = 1;
            mtlDesc.mipmapLevelCount = 1;
            mtlDesc.arrayLength = 1;
            mtlDesc.storageMode = MTLStorageModePrivate;
            mtlDesc.sampleCount = 1;

            id<MTLTexture> texture = [device->GetMTLDevice() newTextureWithDescriptor:mtlDesc];
            if (texture == nil) {
                return DAWN_OUT_OF_MEMORY_ERROR("Allocation of temporary texture failed.");
            }

            return AcquireNSPRef(texture);
        }

        void CopyIntoTrueResolveTarget(CommandRecordingContext* commandContext,
                                       id<MTLTexture> mtlTrueResolveTexture,
                                       uint32_t trueResolveLevel,
                                       uint32_t trueResolveSlice,
                                       id<MTLTexture> temporaryResolveTexture,
                                       uint32_t width,
                                       uint32_t height) {
            [commandContext->EnsureBlit() copyFromTexture:temporaryResolveTexture
                                              sourceSlice:0
                                              sourceLevel:0
                                             sourceOrigin:MTLOriginMake(0, 0, 0)
                                               sourceSize:MTLSizeMake(width, height, 1)
                                                toTexture:mtlTrueResolveTexture
                                         destinationSlice:trueResolveSlice
                                         destinationLevel:trueResolveLevel
                                        destinationOrigin:MTLOriginMake(0, 0, 0)];
        }

        // Metal uses a physical addressing mode which means buffers in the shading language are
        // just pointers to the virtual address of their start. This means there is no way to know
        // the length of a buffer to compute the length() of unsized arrays at the end of storage
        // buffers. SPIRV-Cross implements the length() of unsized arrays by requiring an extra
        // buffer that contains the length of other buffers. This structure that keeps track of the
        // length of storage buffers and can apply them to the reserved "buffer length buffer" when
        // needed for a draw or a dispatch.
        struct StorageBufferLengthTracker {
            wgpu::ShaderStage dirtyStages = wgpu::ShaderStage::None;

            // The lengths of buffers are stored as 32bit integers because that is the width the
            // MSL code generated by SPIRV-Cross expects.
            // UBOs require we align the max buffer count to 4 elements (16 bytes).
            static constexpr size_t MaxBufferCount = ((kGenericMetalBufferSlots + 3) / 4) * 4;
            PerStage<std::array<uint32_t, MaxBufferCount>> data;

            void Apply(id<MTLRenderCommandEncoder> render,
                       RenderPipeline* pipeline,
                       bool enableVertexPulling) {
                wgpu::ShaderStage stagesToApply =
                    dirtyStages & pipeline->GetStagesRequiringStorageBufferLength();

                if (stagesToApply == wgpu::ShaderStage::None) {
                    return;
                }

                if (stagesToApply & wgpu::ShaderStage::Vertex) {
                    uint32_t bufferCount = ToBackend(pipeline->GetLayout())
                                               ->GetBufferBindingCount(SingleShaderStage::Vertex);

                    if (enableVertexPulling) {
                        bufferCount += pipeline->GetVertexBufferCount();
                    }

                    bufferCount = Align(bufferCount, 4);
                    ASSERT(bufferCount <= data[SingleShaderStage::Vertex].size());

                    [render setVertexBytes:data[SingleShaderStage::Vertex].data()
                                    length:sizeof(uint32_t) * bufferCount
                                   atIndex:kBufferLengthBufferSlot];
                }

                if (stagesToApply & wgpu::ShaderStage::Fragment) {
                    uint32_t bufferCount = ToBackend(pipeline->GetLayout())
                                               ->GetBufferBindingCount(SingleShaderStage::Fragment);
                    bufferCount = Align(bufferCount, 4);
                    ASSERT(bufferCount <= data[SingleShaderStage::Fragment].size());

                    [render setFragmentBytes:data[SingleShaderStage::Fragment].data()
                                      length:sizeof(uint32_t) * bufferCount
                                     atIndex:kBufferLengthBufferSlot];
                }

                // Only mark clean stages that were actually applied.
                dirtyStages ^= stagesToApply;
            }

            void Apply(id<MTLComputeCommandEncoder> compute, ComputePipeline* pipeline) {
                if (!(dirtyStages & wgpu::ShaderStage::Compute)) {
                    return;
                }

                if (!pipeline->RequiresStorageBufferLength()) {
                    return;
                }

                uint32_t bufferCount = ToBackend(pipeline->GetLayout())
                                           ->GetBufferBindingCount(SingleShaderStage::Compute);
                bufferCount = Align(bufferCount, 4);
                ASSERT(bufferCount <= data[SingleShaderStage::Compute].size());

                [compute setBytes:data[SingleShaderStage::Compute].data()
                           length:sizeof(uint32_t) * bufferCount
                          atIndex:kBufferLengthBufferSlot];

                dirtyStages ^= wgpu::ShaderStage::Compute;
            }
        };

        // Keeps track of the dirty bind groups so they can be lazily applied when we know the
        // pipeline state.
        // Bind groups may be inherited because bind groups are packed in the buffer /
        // texture tables in contiguous order.
        class BindGroupTracker : public BindGroupTrackerBase<true, uint64_t> {
          public:
            explicit BindGroupTracker(StorageBufferLengthTracker* lengthTracker)
                : BindGroupTrackerBase(), mLengthTracker(lengthTracker) {
            }

            template <typename Encoder>
            void Apply(Encoder encoder) {
                BeforeApply();
                for (BindGroupIndex index :
                     IterateBitSet(mDirtyBindGroupsObjectChangedOrIsDynamic)) {
                    ApplyBindGroup(encoder, index, ToBackend(mBindGroups[index]),
                                   mDynamicOffsetCounts[index], mDynamicOffsets[index].data(),
                                   ToBackend(mPipelineLayout));
                }
                AfterApply();
            }

          private:
            // Handles a call to SetBindGroup, directing the commands to the correct encoder.
            // There is a single function that takes both encoders to factor code. Other approaches
            // like templates wouldn't work because the name of methods are different between the
            // two encoder types.
            void ApplyBindGroupImpl(id<MTLRenderCommandEncoder> render,
                                    id<MTLComputeCommandEncoder> compute,
                                    BindGroupIndex index,
                                    BindGroup* group,
                                    uint32_t dynamicOffsetCount,
                                    uint64_t* dynamicOffsets,
                                    PipelineLayout* pipelineLayout) {
                uint32_t currentDynamicBufferIndex = 0;

                // TODO(crbug.com/dawn/854): Maintain buffers and offsets arrays in BindGroup
                // so that we only have to do one setVertexBuffers and one setFragmentBuffers
                // call here.
                for (BindingIndex bindingIndex{0};
                     bindingIndex < group->GetLayout()->GetBindingCount(); ++bindingIndex) {
                    const BindingInfo& bindingInfo =
                        group->GetLayout()->GetBindingInfo(bindingIndex);

                    bool hasVertStage =
                        bindingInfo.visibility & wgpu::ShaderStage::Vertex && render != nullptr;
                    bool hasFragStage =
                        bindingInfo.visibility & wgpu::ShaderStage::Fragment && render != nullptr;
                    bool hasComputeStage =
                        bindingInfo.visibility & wgpu::ShaderStage::Compute && compute != nullptr;

                    uint32_t vertIndex = 0;
                    uint32_t fragIndex = 0;
                    uint32_t computeIndex = 0;

                    if (hasVertStage) {
                        vertIndex = pipelineLayout->GetBindingIndexInfo(
                            SingleShaderStage::Vertex)[index][bindingIndex];
                    }
                    if (hasFragStage) {
                        fragIndex = pipelineLayout->GetBindingIndexInfo(
                            SingleShaderStage::Fragment)[index][bindingIndex];
                    }
                    if (hasComputeStage) {
                        computeIndex = pipelineLayout->GetBindingIndexInfo(
                            SingleShaderStage::Compute)[index][bindingIndex];
                    }

                    switch (bindingInfo.bindingType) {
                        case BindingInfoType::Buffer: {
                            const BufferBinding& binding =
                                group->GetBindingAsBufferBinding(bindingIndex);
                            const id<MTLBuffer> buffer = ToBackend(binding.buffer)->GetMTLBuffer();
                            NSUInteger offset = binding.offset;

                            // TODO(crbug.com/dawn/854): Record bound buffer status to use
                            // setBufferOffset to achieve better performance.
                            if (bindingInfo.buffer.hasDynamicOffset) {
                                offset += dynamicOffsets[currentDynamicBufferIndex];
                                currentDynamicBufferIndex++;
                            }

                            if (hasVertStage) {
                                mLengthTracker->data[SingleShaderStage::Vertex][vertIndex] =
                                    binding.size;
                                mLengthTracker->dirtyStages |= wgpu::ShaderStage::Vertex;
                                [render setVertexBuffers:&buffer
                                                 offsets:&offset
                                               withRange:NSMakeRange(vertIndex, 1)];
                            }
                            if (hasFragStage) {
                                mLengthTracker->data[SingleShaderStage::Fragment][fragIndex] =
                                    binding.size;
                                mLengthTracker->dirtyStages |= wgpu::ShaderStage::Fragment;
                                [render setFragmentBuffers:&buffer
                                                   offsets:&offset
                                                 withRange:NSMakeRange(fragIndex, 1)];
                            }
                            if (hasComputeStage) {
                                mLengthTracker->data[SingleShaderStage::Compute][computeIndex] =
                                    binding.size;
                                mLengthTracker->dirtyStages |= wgpu::ShaderStage::Compute;
                                [compute setBuffers:&buffer
                                            offsets:&offset
                                          withRange:NSMakeRange(computeIndex, 1)];
                            }

                            break;
                        }

                        case BindingInfoType::Sampler: {
                            auto sampler = ToBackend(group->GetBindingAsSampler(bindingIndex));
                            if (hasVertStage) {
                                [render setVertexSamplerState:sampler->GetMTLSamplerState()
                                                      atIndex:vertIndex];
                            }
                            if (hasFragStage) {
                                [render setFragmentSamplerState:sampler->GetMTLSamplerState()
                                                        atIndex:fragIndex];
                            }
                            if (hasComputeStage) {
                                [compute setSamplerState:sampler->GetMTLSamplerState()
                                                 atIndex:computeIndex];
                            }
                            break;
                        }

                        case BindingInfoType::Texture:
                        case BindingInfoType::StorageTexture: {
                            auto textureView =
                                ToBackend(group->GetBindingAsTextureView(bindingIndex));
                            if (hasVertStage) {
                                [render setVertexTexture:textureView->GetMTLTexture()
                                                 atIndex:vertIndex];
                            }
                            if (hasFragStage) {
                                [render setFragmentTexture:textureView->GetMTLTexture()
                                                   atIndex:fragIndex];
                            }
                            if (hasComputeStage) {
                                [compute setTexture:textureView->GetMTLTexture()
                                            atIndex:computeIndex];
                            }
                            break;
                        }

                        case BindingInfoType::ExternalTexture: {
                            const std::array<Ref<TextureViewBase>, kMaxPlanesPerFormat>& views =
                                group->GetBindingAsExternalTexture(bindingIndex)->GetTextureViews();

                            // Only single-plane formats are supported right now, so assert only one
                            // view exists.
                            ASSERT(views[1].Get() == nullptr);
                            ASSERT(views[2].Get() == nullptr);

                            TextureView* textureView = ToBackend(views[0].Get());

                            if (hasVertStage) {
                                [render setVertexTexture:textureView->GetMTLTexture()
                                                 atIndex:vertIndex];
                            }
                            if (hasFragStage) {
                                [render setFragmentTexture:textureView->GetMTLTexture()
                                                   atIndex:fragIndex];
                            }
                            if (hasComputeStage) {
                                [compute setTexture:textureView->GetMTLTexture()
                                            atIndex:computeIndex];
                            }
                            break;
                        }
                    }
                }
            }

            template <typename... Args>
            void ApplyBindGroup(id<MTLRenderCommandEncoder> encoder, Args&&... args) {
                ApplyBindGroupImpl(encoder, nullptr, std::forward<Args&&>(args)...);
            }

            template <typename... Args>
            void ApplyBindGroup(id<MTLComputeCommandEncoder> encoder, Args&&... args) {
                ApplyBindGroupImpl(nullptr, encoder, std::forward<Args&&>(args)...);
            }

            StorageBufferLengthTracker* mLengthTracker;
        };

        // Keeps track of the dirty vertex buffer values so they can be lazily applied when we know
        // all the relevant state.
        class VertexBufferTracker {
          public:
            explicit VertexBufferTracker(StorageBufferLengthTracker* lengthTracker)
                : mLengthTracker(lengthTracker) {
            }

            void OnSetVertexBuffer(VertexBufferSlot slot, Buffer* buffer, uint64_t offset) {
                mVertexBuffers[slot] = buffer->GetMTLBuffer();
                mVertexBufferOffsets[slot] = offset;

                ASSERT(buffer->GetSize() < std::numeric_limits<uint32_t>::max());
                mVertexBufferBindingSizes[slot] =
                    static_cast<uint32_t>(buffer->GetAllocatedSize() - offset);
                mDirtyVertexBuffers.set(slot);
            }

            void OnSetPipeline(RenderPipeline* lastPipeline, RenderPipeline* pipeline) {
                // When a new pipeline is bound we must set all the vertex buffers again because
                // they might have been offset by the pipeline layout, and they might be packed
                // differently from the previous pipeline.
                mDirtyVertexBuffers |= pipeline->GetVertexBufferSlotsUsed();
            }

            void Apply(id<MTLRenderCommandEncoder> encoder,
                       RenderPipeline* pipeline,
                       bool enableVertexPulling) {
                const auto& vertexBuffersToApply =
                    mDirtyVertexBuffers & pipeline->GetVertexBufferSlotsUsed();

                for (VertexBufferSlot slot : IterateBitSet(vertexBuffersToApply)) {
                    uint32_t metalIndex = pipeline->GetMtlVertexBufferIndex(slot);

                    if (enableVertexPulling) {
                        // Insert lengths for vertex buffers bound as storage buffers
                        mLengthTracker->data[SingleShaderStage::Vertex][metalIndex] =
                            mVertexBufferBindingSizes[slot];
                        mLengthTracker->dirtyStages |= wgpu::ShaderStage::Vertex;
                    }

                    [encoder setVertexBuffers:&mVertexBuffers[slot]
                                      offsets:&mVertexBufferOffsets[slot]
                                    withRange:NSMakeRange(metalIndex, 1)];
                }

                mDirtyVertexBuffers.reset();
            }

          private:
            // All the indices in these arrays are Dawn vertex buffer indices
            ityp::bitset<VertexBufferSlot, kMaxVertexBuffers> mDirtyVertexBuffers;
            ityp::array<VertexBufferSlot, id<MTLBuffer>, kMaxVertexBuffers> mVertexBuffers;
            ityp::array<VertexBufferSlot, NSUInteger, kMaxVertexBuffers> mVertexBufferOffsets;
            ityp::array<VertexBufferSlot, uint32_t, kMaxVertexBuffers> mVertexBufferBindingSizes;

            StorageBufferLengthTracker* mLengthTracker;
        };

    }  // anonymous namespace

    void RecordCopyBufferToTexture(CommandRecordingContext* commandContext,
                                   id<MTLBuffer> mtlBuffer,
                                   uint64_t bufferSize,
                                   uint64_t offset,
                                   uint32_t bytesPerRow,
                                   uint32_t rowsPerImage,
                                   Texture* texture,
                                   uint32_t mipLevel,
                                   const Origin3D& origin,
                                   Aspect aspect,
                                   const Extent3D& copySize) {
        TextureBufferCopySplit splitCopies =
            ComputeTextureBufferCopySplit(texture, mipLevel, origin, copySize, bufferSize, offset,
                                          bytesPerRow, rowsPerImage, aspect);

        MTLBlitOption blitOption = ComputeMTLBlitOption(texture->GetFormat(), aspect);

        for (const auto& copyInfo : splitCopies) {
            uint64_t bufferOffset = copyInfo.bufferOffset;
            switch (texture->GetDimension()) {
                case wgpu::TextureDimension::e2D: {
                    const MTLOrigin textureOrigin =
                        MTLOriginMake(copyInfo.textureOrigin.x, copyInfo.textureOrigin.y, 0);
                    const MTLSize copyExtent =
                        MTLSizeMake(copyInfo.copyExtent.width, copyInfo.copyExtent.height, 1);

                    for (uint32_t z = copyInfo.textureOrigin.z;
                         z < copyInfo.textureOrigin.z + copyInfo.copyExtent.depthOrArrayLayers;
                         ++z) {
                        [commandContext->EnsureBlit() copyFromBuffer:mtlBuffer
                                                        sourceOffset:bufferOffset
                                                   sourceBytesPerRow:copyInfo.bytesPerRow
                                                 sourceBytesPerImage:copyInfo.bytesPerImage
                                                          sourceSize:copyExtent
                                                           toTexture:texture->GetMTLTexture()
                                                    destinationSlice:z
                                                    destinationLevel:mipLevel
                                                   destinationOrigin:textureOrigin
                                                             options:blitOption];
                        bufferOffset += copyInfo.bytesPerImage;
                    }
                    break;
                }
                case wgpu::TextureDimension::e3D: {
                    [commandContext->EnsureBlit()
                             copyFromBuffer:mtlBuffer
                               sourceOffset:bufferOffset
                          sourceBytesPerRow:copyInfo.bytesPerRow
                        sourceBytesPerImage:copyInfo.bytesPerImage
                                 sourceSize:MTLSizeMake(copyInfo.copyExtent.width,
                                                        copyInfo.copyExtent.height,
                                                        copyInfo.copyExtent.depthOrArrayLayers)
                                  toTexture:texture->GetMTLTexture()
                           destinationSlice:0
                           destinationLevel:mipLevel
                          destinationOrigin:MTLOriginMake(copyInfo.textureOrigin.x,
                                                          copyInfo.textureOrigin.y,
                                                          copyInfo.textureOrigin.z)
                                    options:blitOption];
                    break;
                }
                case wgpu::TextureDimension::e1D:
                    UNREACHABLE();
            }
        }
    }

    // static
    Ref<CommandBuffer> CommandBuffer::Create(CommandEncoder* encoder,
                                             const CommandBufferDescriptor* descriptor) {
        return AcquireRef(new CommandBuffer(encoder, descriptor));
    }

    MaybeError CommandBuffer::FillCommands(CommandRecordingContext* commandContext) {
        size_t nextComputePassNumber = 0;
        size_t nextRenderPassNumber = 0;

        auto LazyClearSyncScope = [](const SyncScopeResourceUsage& scope,
                                     CommandRecordingContext* commandContext) {
            for (size_t i = 0; i < scope.textures.size(); ++i) {
                Texture* texture = ToBackend(scope.textures[i]);

                // Clear subresources that are not render attachments. Render attachments will be
                // cleared in RecordBeginRenderPass by setting the loadop to clear when the texture
                // subresource has not been initialized before the render pass.
                scope.textureUsages[i].Iterate(
                    [&](const SubresourceRange& range, wgpu::TextureUsage usage) {
                        if (usage & ~wgpu::TextureUsage::RenderAttachment) {
                            texture->EnsureSubresourceContentInitialized(commandContext, range);
                        }
                    });
            }
            for (BufferBase* bufferBase : scope.buffers) {
                ToBackend(bufferBase)->EnsureDataInitialized(commandContext);
            }
        };

        Command type;
        while (mCommands.NextCommandId(&type)) {
            switch (type) {
                case Command::BeginComputePass: {
                    mCommands.NextCommand<BeginComputePassCmd>();

                    for (const SyncScopeResourceUsage& scope :
                         GetResourceUsages().computePasses[nextComputePassNumber].dispatchUsages) {
                        LazyClearSyncScope(scope, commandContext);
                    }
                    commandContext->EndBlit();

                    DAWN_TRY(EncodeComputePass(commandContext));

                    nextComputePassNumber++;
                    break;
                }

                case Command::BeginRenderPass: {
                    BeginRenderPassCmd* cmd = mCommands.NextCommand<BeginRenderPassCmd>();

                    LazyClearSyncScope(GetResourceUsages().renderPasses[nextRenderPassNumber],
                                       commandContext);
                    commandContext->EndBlit();

                    LazyClearRenderPassAttachments(cmd);
                    NSRef<MTLRenderPassDescriptor> descriptor = CreateMTLRenderPassDescriptor(cmd);
                    DAWN_TRY(EncodeRenderPass(commandContext, descriptor.Get(), cmd->width,
                                              cmd->height));

                    nextRenderPassNumber++;
                    break;
                }

                case Command::CopyBufferToBuffer: {
                    CopyBufferToBufferCmd* copy = mCommands.NextCommand<CopyBufferToBufferCmd>();
                    if (copy->size == 0) {
                        // Skip no-op copies.
                        break;
                    }

                    ToBackend(copy->source)->EnsureDataInitialized(commandContext);
                    ToBackend(copy->destination)
                        ->EnsureDataInitializedAsDestination(commandContext,
                                                             copy->destinationOffset, copy->size);

                    [commandContext->EnsureBlit()
                           copyFromBuffer:ToBackend(copy->source)->GetMTLBuffer()
                             sourceOffset:copy->sourceOffset
                                 toBuffer:ToBackend(copy->destination)->GetMTLBuffer()
                        destinationOffset:copy->destinationOffset
                                     size:copy->size];
                    break;
                }

                case Command::CopyBufferToTexture: {
                    CopyBufferToTextureCmd* copy = mCommands.NextCommand<CopyBufferToTextureCmd>();
                    if (copy->copySize.width == 0 || copy->copySize.height == 0 ||
                        copy->copySize.depthOrArrayLayers == 0) {
                        // Skip no-op copies.
                        continue;
                    }
                    auto& src = copy->source;
                    auto& dst = copy->destination;
                    auto& copySize = copy->copySize;
                    Buffer* buffer = ToBackend(src.buffer.Get());
                    Texture* texture = ToBackend(dst.texture.Get());

                    buffer->EnsureDataInitialized(commandContext);
                    EnsureDestinationTextureInitialized(commandContext, texture, dst, copySize);

                    RecordCopyBufferToTexture(commandContext, buffer->GetMTLBuffer(),
                                              buffer->GetSize(), src.offset, src.bytesPerRow,
                                              src.rowsPerImage, texture, dst.mipLevel, dst.origin,
                                              dst.aspect, copySize);
                    break;
                }

                case Command::CopyTextureToBuffer: {
                    CopyTextureToBufferCmd* copy = mCommands.NextCommand<CopyTextureToBufferCmd>();
                    if (copy->copySize.width == 0 || copy->copySize.height == 0 ||
                        copy->copySize.depthOrArrayLayers == 0) {
                        // Skip no-op copies.
                        continue;
                    }
                    auto& src = copy->source;
                    auto& dst = copy->destination;
                    auto& copySize = copy->copySize;
                    Texture* texture = ToBackend(src.texture.Get());
                    Buffer* buffer = ToBackend(dst.buffer.Get());

                    buffer->EnsureDataInitializedAsDestination(commandContext, copy);

                    texture->EnsureSubresourceContentInitialized(
                        commandContext, GetSubresourcesAffectedByCopy(src, copySize));

                    TextureBufferCopySplit splitCopies = ComputeTextureBufferCopySplit(
                        texture, src.mipLevel, src.origin, copySize, buffer->GetSize(), dst.offset,
                        dst.bytesPerRow, dst.rowsPerImage, src.aspect);

                    for (const auto& copyInfo : splitCopies) {
                        MTLBlitOption blitOption =
                            ComputeMTLBlitOption(texture->GetFormat(), src.aspect);
                        uint64_t bufferOffset = copyInfo.bufferOffset;

                        switch (texture->GetDimension()) {
                            case wgpu::TextureDimension::e2D: {
                                const MTLOrigin textureOrigin = MTLOriginMake(
                                    copyInfo.textureOrigin.x, copyInfo.textureOrigin.y, 0);
                                const MTLSize copyExtent = MTLSizeMake(
                                    copyInfo.copyExtent.width, copyInfo.copyExtent.height, 1);

                                for (uint32_t z = copyInfo.textureOrigin.z;
                                     z < copyInfo.textureOrigin.z +
                                             copyInfo.copyExtent.depthOrArrayLayers;
                                     ++z) {
                                    [commandContext->EnsureBlit()
                                                 copyFromTexture:texture->GetMTLTexture()
                                                     sourceSlice:z
                                                     sourceLevel:src.mipLevel
                                                    sourceOrigin:textureOrigin
                                                      sourceSize:copyExtent
                                                        toBuffer:buffer->GetMTLBuffer()
                                               destinationOffset:bufferOffset
                                          destinationBytesPerRow:copyInfo.bytesPerRow
                                        destinationBytesPerImage:copyInfo.bytesPerImage
                                                         options:blitOption];
                                    bufferOffset += copyInfo.bytesPerImage;
                                }
                                break;
                            }
                            case wgpu::TextureDimension::e3D: {
                                [commandContext->EnsureBlit()
                                             copyFromTexture:texture->GetMTLTexture()
                                                 sourceSlice:0
                                                 sourceLevel:src.mipLevel
                                                sourceOrigin:MTLOriginMake(copyInfo.textureOrigin.x,
                                                                           copyInfo.textureOrigin.y,
                                                                           copyInfo.textureOrigin.z)
                                                  sourceSize:MTLSizeMake(copyInfo.copyExtent.width,
                                                                         copyInfo.copyExtent.height,
                                                                         copyInfo.copyExtent
                                                                             .depthOrArrayLayers)
                                                    toBuffer:buffer->GetMTLBuffer()
                                           destinationOffset:bufferOffset
                                      destinationBytesPerRow:copyInfo.bytesPerRow
                                    destinationBytesPerImage:copyInfo.bytesPerImage
                                                     options:blitOption];
                                break;
                            }
                            case wgpu::TextureDimension::e1D:
                                UNREACHABLE();
                        }
                    }
                    break;
                }

                case Command::CopyTextureToTexture: {
                    CopyTextureToTextureCmd* copy =
                        mCommands.NextCommand<CopyTextureToTextureCmd>();
                    if (copy->copySize.width == 0 || copy->copySize.height == 0 ||
                        copy->copySize.depthOrArrayLayers == 0) {
                        // Skip no-op copies.
                        continue;
                    }
                    Texture* srcTexture = ToBackend(copy->source.texture.Get());
                    Texture* dstTexture = ToBackend(copy->destination.texture.Get());

                    srcTexture->EnsureSubresourceContentInitialized(
                        commandContext,
                        GetSubresourcesAffectedByCopy(copy->source, copy->copySize));
                    EnsureDestinationTextureInitialized(commandContext, dstTexture,
                                                        copy->destination, copy->copySize);

                    // TODO(crbug.com/dawn/814): support copies with 1D textures.
                    ASSERT(srcTexture->GetDimension() != wgpu::TextureDimension::e1D &&
                           dstTexture->GetDimension() != wgpu::TextureDimension::e1D);

                    const MTLSize sizeOneSlice =
                        MTLSizeMake(copy->copySize.width, copy->copySize.height, 1);

                    uint32_t sourceLayer = 0;
                    uint32_t sourceOriginZ = 0;

                    uint32_t destinationLayer = 0;
                    uint32_t destinationOriginZ = 0;

                    uint32_t* sourceZPtr;
                    if (srcTexture->GetDimension() == wgpu::TextureDimension::e2D) {
                        sourceZPtr = &sourceLayer;
                    } else {
                        sourceZPtr = &sourceOriginZ;
                    }

                    uint32_t* destinationZPtr;
                    if (dstTexture->GetDimension() == wgpu::TextureDimension::e2D) {
                        destinationZPtr = &destinationLayer;
                    } else {
                        destinationZPtr = &destinationOriginZ;
                    }

                    // TODO(crbug.com/dawn/782): Do a single T2T copy if both are 3D.
                    for (uint32_t z = 0; z < copy->copySize.depthOrArrayLayers; ++z) {
                        *sourceZPtr = copy->source.origin.z + z;
                        *destinationZPtr = copy->destination.origin.z + z;

                        [commandContext->EnsureBlit()
                              copyFromTexture:srcTexture->GetMTLTexture()
                                  sourceSlice:sourceLayer
                                  sourceLevel:copy->source.mipLevel
                                 sourceOrigin:MTLOriginMake(copy->source.origin.x,
                                                            copy->source.origin.y, sourceOriginZ)
                                   sourceSize:sizeOneSlice
                                    toTexture:dstTexture->GetMTLTexture()
                             destinationSlice:destinationLayer
                             destinationLevel:copy->destination.mipLevel
                            destinationOrigin:MTLOriginMake(copy->destination.origin.x,
                                                            copy->destination.origin.y,
                                                            destinationOriginZ)];
                    }
                    break;
                }

                case Command::ResolveQuerySet: {
                    ResolveQuerySetCmd* cmd = mCommands.NextCommand<ResolveQuerySetCmd>();
                    QuerySet* querySet = ToBackend(cmd->querySet.Get());
                    Buffer* destination = ToBackend(cmd->destination.Get());

                    destination->EnsureDataInitializedAsDestination(
                        commandContext, cmd->destinationOffset, cmd->queryCount * sizeof(uint64_t));

                    if (querySet->GetQueryType() == wgpu::QueryType::Occlusion) {
                        [commandContext->EnsureBlit()
                               copyFromBuffer:querySet->GetVisibilityBuffer()
                                 sourceOffset:NSUInteger(cmd->firstQuery * sizeof(uint64_t))
                                     toBuffer:destination->GetMTLBuffer()
                            destinationOffset:NSUInteger(cmd->destinationOffset)
                                         size:NSUInteger(cmd->queryCount * sizeof(uint64_t))];
                    } else {
                        if (@available(macos 10.15, iOS 14.0, *)) {
                            [commandContext->EnsureBlit()
                                  resolveCounters:querySet->GetCounterSampleBuffer()
                                          inRange:NSMakeRange(cmd->firstQuery,
                                                              cmd->firstQuery + cmd->queryCount)
                                destinationBuffer:destination->GetMTLBuffer()
                                destinationOffset:NSUInteger(cmd->destinationOffset)];
                        } else {
                            UNREACHABLE();
                        }
                    }
                    break;
                }

                case Command::WriteTimestamp: {
                    WriteTimestampCmd* cmd = mCommands.NextCommand<WriteTimestampCmd>();
                    QuerySet* querySet = ToBackend(cmd->querySet.Get());

                    if (@available(macos 10.15, iOS 14.0, *)) {
                        [commandContext->EnsureBlit()
                            sampleCountersInBuffer:querySet->GetCounterSampleBuffer()
                                     atSampleIndex:NSUInteger(cmd->queryIndex)
                                       withBarrier:YES];
                    } else {
                        UNREACHABLE();
                    }
                    break;
                }

                case Command::InsertDebugMarker: {
                    // MTLCommandBuffer does not implement insertDebugSignpost
                    SkipCommand(&mCommands, type);
                    break;
                }

                case Command::PopDebugGroup: {
                    mCommands.NextCommand<PopDebugGroupCmd>();

                    if (@available(macos 10.13, *)) {
                        [commandContext->GetCommands() popDebugGroup];
                    }
                    break;
                }

                case Command::PushDebugGroup: {
                    PushDebugGroupCmd* cmd = mCommands.NextCommand<PushDebugGroupCmd>();
                    char* label = mCommands.NextData<char>(cmd->length + 1);

                    if (@available(macos 10.13, *)) {
                        NSRef<NSString> mtlLabel =
                            AcquireNSRef([[NSString alloc] initWithUTF8String:label]);
                        [commandContext->GetCommands() pushDebugGroup:mtlLabel.Get()];
                    }

                    break;
                }

                default:
                    UNREACHABLE();
            }
        }

        commandContext->EndBlit();
        return {};
    }

    MaybeError CommandBuffer::EncodeComputePass(CommandRecordingContext* commandContext) {
        ComputePipeline* lastPipeline = nullptr;
        StorageBufferLengthTracker storageBufferLengths = {};
        BindGroupTracker bindGroups(&storageBufferLengths);

        id<MTLComputeCommandEncoder> encoder = commandContext->BeginCompute();

        Command type;
        while (mCommands.NextCommandId(&type)) {
            switch (type) {
                case Command::EndComputePass: {
                    mCommands.NextCommand<EndComputePassCmd>();
                    commandContext->EndCompute();
                    return {};
                }

                case Command::Dispatch: {
                    DispatchCmd* dispatch = mCommands.NextCommand<DispatchCmd>();

                    // Skip noop dispatches, it can causes issues on some systems.
                    if (dispatch->x == 0 || dispatch->y == 0 || dispatch->z == 0) {
                        break;
                    }

                    bindGroups.Apply(encoder);
                    storageBufferLengths.Apply(encoder, lastPipeline);

                    [encoder dispatchThreadgroups:MTLSizeMake(dispatch->x, dispatch->y, dispatch->z)
                            threadsPerThreadgroup:lastPipeline->GetLocalWorkGroupSize()];
                    break;
                }

                case Command::DispatchIndirect: {
                    DispatchIndirectCmd* dispatch = mCommands.NextCommand<DispatchIndirectCmd>();

                    bindGroups.Apply(encoder);
                    storageBufferLengths.Apply(encoder, lastPipeline);

                    Buffer* buffer = ToBackend(dispatch->indirectBuffer.Get());
                    id<MTLBuffer> indirectBuffer = buffer->GetMTLBuffer();
                    [encoder dispatchThreadgroupsWithIndirectBuffer:indirectBuffer
                                               indirectBufferOffset:dispatch->indirectOffset
                                              threadsPerThreadgroup:lastPipeline
                                                                        ->GetLocalWorkGroupSize()];
                    break;
                }

                case Command::SetComputePipeline: {
                    SetComputePipelineCmd* cmd = mCommands.NextCommand<SetComputePipelineCmd>();
                    lastPipeline = ToBackend(cmd->pipeline).Get();

                    bindGroups.OnSetPipeline(lastPipeline);

                    lastPipeline->Encode(encoder);
                    break;
                }

                case Command::SetBindGroup: {
                    SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>();
                    uint32_t* dynamicOffsets = nullptr;
                    if (cmd->dynamicOffsetCount > 0) {
                        dynamicOffsets = mCommands.NextData<uint32_t>(cmd->dynamicOffsetCount);
                    }

                    bindGroups.OnSetBindGroup(cmd->index, ToBackend(cmd->group.Get()),
                                              cmd->dynamicOffsetCount, dynamicOffsets);
                    break;
                }

                case Command::InsertDebugMarker: {
                    InsertDebugMarkerCmd* cmd = mCommands.NextCommand<InsertDebugMarkerCmd>();
                    char* label = mCommands.NextData<char>(cmd->length + 1);
                    NSRef<NSString> mtlLabel =
                        AcquireNSRef([[NSString alloc] initWithUTF8String:label]);
                    [encoder insertDebugSignpost:mtlLabel.Get()];
                    break;
                }

                case Command::PopDebugGroup: {
                    mCommands.NextCommand<PopDebugGroupCmd>();

                    [encoder popDebugGroup];
                    break;
                }

                case Command::PushDebugGroup: {
                    PushDebugGroupCmd* cmd = mCommands.NextCommand<PushDebugGroupCmd>();
                    char* label = mCommands.NextData<char>(cmd->length + 1);
                    NSRef<NSString> mtlLabel =
                        AcquireNSRef([[NSString alloc] initWithUTF8String:label]);
                    [encoder pushDebugGroup:mtlLabel.Get()];
                    break;
                }

                case Command::WriteTimestamp: {
                    WriteTimestampCmd* cmd = mCommands.NextCommand<WriteTimestampCmd>();
                    QuerySet* querySet = ToBackend(cmd->querySet.Get());

                    if (@available(macos 10.15, iOS 14.0, *)) {
                        [encoder sampleCountersInBuffer:querySet->GetCounterSampleBuffer()
                                          atSampleIndex:NSUInteger(cmd->queryIndex)
                                            withBarrier:YES];
                    } else {
                        UNREACHABLE();
                    }
                    break;
                }

                default: {
                    UNREACHABLE();
                    break;
                }
            }
        }

        // EndComputePass should have been called
        UNREACHABLE();
    }

    MaybeError CommandBuffer::EncodeRenderPass(CommandRecordingContext* commandContext,
                                               MTLRenderPassDescriptor* mtlRenderPass,
                                               uint32_t width,
                                               uint32_t height) {
        ASSERT(mtlRenderPass);

        Device* device = ToBackend(GetDevice());

        // Handle Toggle AlwaysResolveIntoZeroLevelAndLayer. We must handle this before applying
        // the store + MSAA resolve workaround, otherwise this toggle will never be handled because
        // the resolve texture is removed when applying the store + MSAA resolve workaround.
        if (device->IsToggleEnabled(Toggle::AlwaysResolveIntoZeroLevelAndLayer)) {
            std::array<id<MTLTexture>, kMaxColorAttachments> trueResolveTextures = {};
            std::array<uint32_t, kMaxColorAttachments> trueResolveLevels = {};
            std::array<uint32_t, kMaxColorAttachments> trueResolveSlices = {};

            // Use temporary resolve texture on the resolve targets with non-zero resolveLevel or
            // resolveSlice.
            bool useTemporaryResolveTexture = false;
            std::array<NSPRef<id<MTLTexture>>, kMaxColorAttachments> temporaryResolveTextures = {};
            for (uint32_t i = 0; i < kMaxColorAttachments; ++i) {
                if (mtlRenderPass.colorAttachments[i].resolveTexture == nullptr) {
                    continue;
                }

                if (mtlRenderPass.colorAttachments[i].resolveLevel == 0 &&
                    mtlRenderPass.colorAttachments[i].resolveSlice == 0) {
                    continue;
                }

                trueResolveTextures[i] = mtlRenderPass.colorAttachments[i].resolveTexture;
                trueResolveLevels[i] = mtlRenderPass.colorAttachments[i].resolveLevel;
                trueResolveSlices[i] = mtlRenderPass.colorAttachments[i].resolveSlice;

                const MTLPixelFormat mtlFormat = trueResolveTextures[i].pixelFormat;
                DAWN_TRY_ASSIGN(temporaryResolveTextures[i], CreateResolveTextureForWorkaround(
                                                                 device, mtlFormat, width, height));

                mtlRenderPass.colorAttachments[i].resolveTexture =
                    temporaryResolveTextures[i].Get();
                mtlRenderPass.colorAttachments[i].resolveLevel = 0;
                mtlRenderPass.colorAttachments[i].resolveSlice = 0;
                useTemporaryResolveTexture = true;
            }

            // If we need to use a temporary resolve texture we need to copy the result of MSAA
            // resolve back to the true resolve targets.
            if (useTemporaryResolveTexture) {
                DAWN_TRY(EncodeRenderPass(commandContext, mtlRenderPass, width, height));
                for (uint32_t i = 0; i < kMaxColorAttachments; ++i) {
                    if (trueResolveTextures[i] == nullptr) {
                        continue;
                    }

                    ASSERT(temporaryResolveTextures[i] != nullptr);
                    CopyIntoTrueResolveTarget(commandContext, trueResolveTextures[i],
                                              trueResolveLevels[i], trueResolveSlices[i],
                                              temporaryResolveTextures[i].Get(), width, height);
                }
                return {};
            }
        }

        // Handle Store + MSAA resolve workaround (Toggle EmulateStoreAndMSAAResolve).
        if (device->IsToggleEnabled(Toggle::EmulateStoreAndMSAAResolve)) {
            bool hasStoreAndMSAAResolve = false;

            // Remove any store + MSAA resolve and remember them.
            std::array<id<MTLTexture>, kMaxColorAttachments> resolveTextures = {};
            for (uint32_t i = 0; i < kMaxColorAttachments; ++i) {
                if (mtlRenderPass.colorAttachments[i].storeAction ==
                    kMTLStoreActionStoreAndMultisampleResolve) {
                    hasStoreAndMSAAResolve = true;
                    resolveTextures[i] = mtlRenderPass.colorAttachments[i].resolveTexture;

                    mtlRenderPass.colorAttachments[i].storeAction = MTLStoreActionStore;
                    mtlRenderPass.colorAttachments[i].resolveTexture = nullptr;
                }
            }

            // If we found a store + MSAA resolve we need to resolve in a different render pass.
            if (hasStoreAndMSAAResolve) {
                DAWN_TRY(EncodeRenderPass(commandContext, mtlRenderPass, width, height));
                ResolveInAnotherRenderPass(commandContext, mtlRenderPass, resolveTextures);
                return {};
            }
        }

        DAWN_TRY(EncodeRenderPassInternal(commandContext, mtlRenderPass, width, height));
        return {};
    }

    MaybeError CommandBuffer::EncodeRenderPassInternal(CommandRecordingContext* commandContext,
                                                       MTLRenderPassDescriptor* mtlRenderPass,
                                                       uint32_t width,
                                                       uint32_t height) {
        bool enableVertexPulling = GetDevice()->IsToggleEnabled(Toggle::MetalEnableVertexPulling);
        RenderPipeline* lastPipeline = nullptr;
        id<MTLBuffer> indexBuffer = nullptr;
        uint32_t indexBufferBaseOffset = 0;
        MTLIndexType indexBufferType;
        uint64_t indexFormatSize = 0;

        StorageBufferLengthTracker storageBufferLengths = {};
        VertexBufferTracker vertexBuffers(&storageBufferLengths);
        BindGroupTracker bindGroups(&storageBufferLengths);

        id<MTLRenderCommandEncoder> encoder = commandContext->BeginRender(mtlRenderPass);

        auto EncodeRenderBundleCommand = [&](CommandIterator* iter, Command type) {
            switch (type) {
                case Command::Draw: {
                    DrawCmd* draw = iter->NextCommand<DrawCmd>();

                    vertexBuffers.Apply(encoder, lastPipeline, enableVertexPulling);
                    bindGroups.Apply(encoder);
                    storageBufferLengths.Apply(encoder, lastPipeline, enableVertexPulling);

                    // The instance count must be non-zero, otherwise no-op
                    if (draw->instanceCount != 0) {
                        // MTLFeatureSet_iOS_GPUFamily3_v1 does not support baseInstance
                        if (draw->firstInstance == 0) {
                            [encoder drawPrimitives:lastPipeline->GetMTLPrimitiveTopology()
                                        vertexStart:draw->firstVertex
                                        vertexCount:draw->vertexCount
                                      instanceCount:draw->instanceCount];
                        } else {
                            [encoder drawPrimitives:lastPipeline->GetMTLPrimitiveTopology()
                                        vertexStart:draw->firstVertex
                                        vertexCount:draw->vertexCount
                                      instanceCount:draw->instanceCount
                                       baseInstance:draw->firstInstance];
                        }
                    }
                    break;
                }

                case Command::DrawIndexed: {
                    DrawIndexedCmd* draw = iter->NextCommand<DrawIndexedCmd>();

                    vertexBuffers.Apply(encoder, lastPipeline, enableVertexPulling);
                    bindGroups.Apply(encoder);
                    storageBufferLengths.Apply(encoder, lastPipeline, enableVertexPulling);

                    // The index and instance count must be non-zero, otherwise no-op
                    if (draw->indexCount != 0 && draw->instanceCount != 0) {
                        // MTLFeatureSet_iOS_GPUFamily3_v1 does not support baseInstance and
                        // baseVertex.
                        if (draw->baseVertex == 0 && draw->firstInstance == 0) {
                            [encoder drawIndexedPrimitives:lastPipeline->GetMTLPrimitiveTopology()
                                                indexCount:draw->indexCount
                                                 indexType:indexBufferType
                                               indexBuffer:indexBuffer
                                         indexBufferOffset:indexBufferBaseOffset +
                                                           draw->firstIndex * indexFormatSize
                                             instanceCount:draw->instanceCount];
                        } else {
                            [encoder drawIndexedPrimitives:lastPipeline->GetMTLPrimitiveTopology()
                                                indexCount:draw->indexCount
                                                 indexType:indexBufferType
                                               indexBuffer:indexBuffer
                                         indexBufferOffset:indexBufferBaseOffset +
                                                           draw->firstIndex * indexFormatSize
                                             instanceCount:draw->instanceCount
                                                baseVertex:draw->baseVertex
                                              baseInstance:draw->firstInstance];
                        }
                    }
                    break;
                }

                case Command::DrawIndirect: {
                    DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>();

                    vertexBuffers.Apply(encoder, lastPipeline, enableVertexPulling);
                    bindGroups.Apply(encoder);
                    storageBufferLengths.Apply(encoder, lastPipeline, enableVertexPulling);

                    Buffer* buffer = ToBackend(draw->indirectBuffer.Get());
                    id<MTLBuffer> indirectBuffer = buffer->GetMTLBuffer();
                    [encoder drawPrimitives:lastPipeline->GetMTLPrimitiveTopology()
                              indirectBuffer:indirectBuffer
                        indirectBufferOffset:draw->indirectOffset];
                    break;
                }

                case Command::DrawIndexedIndirect: {
                    DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>();

                    vertexBuffers.Apply(encoder, lastPipeline, enableVertexPulling);
                    bindGroups.Apply(encoder);
                    storageBufferLengths.Apply(encoder, lastPipeline, enableVertexPulling);

                    Buffer* buffer = ToBackend(draw->indirectBuffer.Get());
                    id<MTLBuffer> indirectBuffer = buffer->GetMTLBuffer();
                    [encoder drawIndexedPrimitives:lastPipeline->GetMTLPrimitiveTopology()
                                         indexType:indexBufferType
                                       indexBuffer:indexBuffer
                                 indexBufferOffset:indexBufferBaseOffset
                                    indirectBuffer:indirectBuffer
                              indirectBufferOffset:draw->indirectOffset];
                    break;
                }

                case Command::InsertDebugMarker: {
                    InsertDebugMarkerCmd* cmd = iter->NextCommand<InsertDebugMarkerCmd>();
                    char* label = iter->NextData<char>(cmd->length + 1);
                    NSRef<NSString> mtlLabel =
                        AcquireNSRef([[NSString alloc] initWithUTF8String:label]);
                    [encoder insertDebugSignpost:mtlLabel.Get()];
                    break;
                }

                case Command::PopDebugGroup: {
                    iter->NextCommand<PopDebugGroupCmd>();

                    [encoder popDebugGroup];
                    break;
                }

                case Command::PushDebugGroup: {
                    PushDebugGroupCmd* cmd = iter->NextCommand<PushDebugGroupCmd>();
                    char* label = iter->NextData<char>(cmd->length + 1);
                    NSRef<NSString> mtlLabel =
                        AcquireNSRef([[NSString alloc] initWithUTF8String:label]);
                    [encoder pushDebugGroup:mtlLabel.Get()];
                    break;
                }

                case Command::SetRenderPipeline: {
                    SetRenderPipelineCmd* cmd = iter->NextCommand<SetRenderPipelineCmd>();
                    RenderPipeline* newPipeline = ToBackend(cmd->pipeline).Get();

                    vertexBuffers.OnSetPipeline(lastPipeline, newPipeline);
                    bindGroups.OnSetPipeline(newPipeline);

                    [encoder setDepthStencilState:newPipeline->GetMTLDepthStencilState()];
                    [encoder setFrontFacingWinding:newPipeline->GetMTLFrontFace()];
                    [encoder setCullMode:newPipeline->GetMTLCullMode()];
                    [encoder setDepthBias:newPipeline->GetDepthBias()
                               slopeScale:newPipeline->GetDepthBiasSlopeScale()
                                    clamp:newPipeline->GetDepthBiasClamp()];
                    if (@available(macOS 10.11, iOS 11.0, *)) {
                        MTLDepthClipMode clipMode = newPipeline->ShouldClampDepth() ?
                            MTLDepthClipModeClamp : MTLDepthClipModeClip;
                        [encoder setDepthClipMode:clipMode];
                    }
                    newPipeline->Encode(encoder);

                    lastPipeline = newPipeline;
                    break;
                }

                case Command::SetBindGroup: {
                    SetBindGroupCmd* cmd = iter->NextCommand<SetBindGroupCmd>();
                    uint32_t* dynamicOffsets = nullptr;
                    if (cmd->dynamicOffsetCount > 0) {
                        dynamicOffsets = iter->NextData<uint32_t>(cmd->dynamicOffsetCount);
                    }

                    bindGroups.OnSetBindGroup(cmd->index, ToBackend(cmd->group.Get()),
                                              cmd->dynamicOffsetCount, dynamicOffsets);
                    break;
                }

                case Command::SetIndexBuffer: {
                    SetIndexBufferCmd* cmd = iter->NextCommand<SetIndexBufferCmd>();
                    auto b = ToBackend(cmd->buffer.Get());
                    indexBuffer = b->GetMTLBuffer();
                    indexBufferBaseOffset = cmd->offset;
                    indexBufferType = MTLIndexFormat(cmd->format);
                    indexFormatSize = IndexFormatSize(cmd->format);
                    break;
                }

                case Command::SetVertexBuffer: {
                    SetVertexBufferCmd* cmd = iter->NextCommand<SetVertexBufferCmd>();

                    vertexBuffers.OnSetVertexBuffer(cmd->slot, ToBackend(cmd->buffer.Get()),
                                                    cmd->offset);
                    break;
                }

                default:
                    UNREACHABLE();
                    break;
            }
        };

        Command type;
        while (mCommands.NextCommandId(&type)) {
            switch (type) {
                case Command::EndRenderPass: {
                    mCommands.NextCommand<EndRenderPassCmd>();
                    commandContext->EndRender();
                    return {};
                }

                case Command::SetStencilReference: {
                    SetStencilReferenceCmd* cmd = mCommands.NextCommand<SetStencilReferenceCmd>();
                    [encoder setStencilReferenceValue:cmd->reference];
                    break;
                }

                case Command::SetViewport: {
                    SetViewportCmd* cmd = mCommands.NextCommand<SetViewportCmd>();
                    MTLViewport viewport;
                    viewport.originX = cmd->x;
                    viewport.originY = cmd->y;
                    viewport.width = cmd->width;
                    viewport.height = cmd->height;
                    viewport.znear = cmd->minDepth;
                    viewport.zfar = cmd->maxDepth;

                    [encoder setViewport:viewport];
                    break;
                }

                case Command::SetScissorRect: {
                    SetScissorRectCmd* cmd = mCommands.NextCommand<SetScissorRectCmd>();
                    MTLScissorRect rect;
                    rect.x = cmd->x;
                    rect.y = cmd->y;
                    rect.width = cmd->width;
                    rect.height = cmd->height;

                    [encoder setScissorRect:rect];
                    break;
                }

                case Command::SetBlendConstant: {
                    SetBlendConstantCmd* cmd = mCommands.NextCommand<SetBlendConstantCmd>();
                    [encoder setBlendColorRed:cmd->color.r
                                        green:cmd->color.g
                                         blue:cmd->color.b
                                        alpha:cmd->color.a];
                    break;
                }

                case Command::ExecuteBundles: {
                    ExecuteBundlesCmd* cmd = mCommands.NextCommand<ExecuteBundlesCmd>();
                    auto bundles = mCommands.NextData<Ref<RenderBundleBase>>(cmd->count);

                    for (uint32_t i = 0; i < cmd->count; ++i) {
                        CommandIterator* iter = bundles[i]->GetCommands();
                        iter->Reset();
                        while (iter->NextCommandId(&type)) {
                            EncodeRenderBundleCommand(iter, type);
                        }
                    }
                    break;
                }

                case Command::BeginOcclusionQuery: {
                    BeginOcclusionQueryCmd* cmd = mCommands.NextCommand<BeginOcclusionQueryCmd>();

                    [encoder setVisibilityResultMode:MTLVisibilityResultModeBoolean
                                              offset:cmd->queryIndex * sizeof(uint64_t)];
                    break;
                }

                case Command::EndOcclusionQuery: {
                    EndOcclusionQueryCmd* cmd = mCommands.NextCommand<EndOcclusionQueryCmd>();

                    [encoder setVisibilityResultMode:MTLVisibilityResultModeDisabled
                                              offset:cmd->queryIndex * sizeof(uint64_t)];
                    break;
                }

                case Command::WriteTimestamp: {
                    WriteTimestampCmd* cmd = mCommands.NextCommand<WriteTimestampCmd>();
                    QuerySet* querySet = ToBackend(cmd->querySet.Get());

                    if (@available(macos 10.15, iOS 14.0, *)) {
                        [encoder sampleCountersInBuffer:querySet->GetCounterSampleBuffer()
                                          atSampleIndex:NSUInteger(cmd->queryIndex)
                                            withBarrier:YES];
                    } else {
                        UNREACHABLE();
                    }
                    break;
                }

                default: {
                    EncodeRenderBundleCommand(&mCommands, type);
                    break;
                }
            }
        }

        // EndRenderPass should have been called
        UNREACHABLE();
    }

}}  // namespace dawn_native::metal
