// Copyright 2017 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "dawn/native/opengl/CommandBufferGL.h"

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

#include "dawn/common/MatchVariant.h"
#include "dawn/native/BindGroup.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/opengl/BindingPoint.h"
#include "dawn/native/opengl/BufferGL.h"
#include "dawn/native/opengl/ComputePipelineGL.h"
#include "dawn/native/opengl/DeviceGL.h"
#include "dawn/native/opengl/Forward.h"
#include "dawn/native/opengl/PersistentPipelineStateGL.h"
#include "dawn/native/opengl/PipelineLayoutGL.h"
#include "dawn/native/opengl/QuerySetGL.h"
#include "dawn/native/opengl/RenderPipelineGL.h"
#include "dawn/native/opengl/SamplerGL.h"
#include "dawn/native/opengl/TextureGL.h"
#include "dawn/native/opengl/UtilsGL.h"
#include "partition_alloc/pointers/raw_ptr.h"

namespace dawn::native::opengl {

namespace {

GLenum IndexFormatType(wgpu::IndexFormat format) {
    switch (format) {
        case wgpu::IndexFormat::Uint16:
            return GL_UNSIGNED_SHORT;
        case wgpu::IndexFormat::Uint32:
            return GL_UNSIGNED_INT;
        case wgpu::IndexFormat::Undefined:
            break;
    }
    DAWN_UNREACHABLE();
}

GLenum VertexFormatType(wgpu::VertexFormat format) {
    switch (format) {
        case wgpu::VertexFormat::Uint8x2:
        case wgpu::VertexFormat::Uint8x4:
        case wgpu::VertexFormat::Unorm8x2:
        case wgpu::VertexFormat::Unorm8x4:
            return GL_UNSIGNED_BYTE;
        case wgpu::VertexFormat::Sint8x2:
        case wgpu::VertexFormat::Sint8x4:
        case wgpu::VertexFormat::Snorm8x2:
        case wgpu::VertexFormat::Snorm8x4:
            return GL_BYTE;
        case wgpu::VertexFormat::Uint16x2:
        case wgpu::VertexFormat::Uint16x4:
        case wgpu::VertexFormat::Unorm16x2:
        case wgpu::VertexFormat::Unorm16x4:
            return GL_UNSIGNED_SHORT;
        case wgpu::VertexFormat::Sint16x2:
        case wgpu::VertexFormat::Sint16x4:
        case wgpu::VertexFormat::Snorm16x2:
        case wgpu::VertexFormat::Snorm16x4:
            return GL_SHORT;
        case wgpu::VertexFormat::Float16x2:
        case wgpu::VertexFormat::Float16x4:
            return GL_HALF_FLOAT;
        case wgpu::VertexFormat::Float32:
        case wgpu::VertexFormat::Float32x2:
        case wgpu::VertexFormat::Float32x3:
        case wgpu::VertexFormat::Float32x4:
            return GL_FLOAT;
        case wgpu::VertexFormat::Uint32:
        case wgpu::VertexFormat::Uint32x2:
        case wgpu::VertexFormat::Uint32x3:
        case wgpu::VertexFormat::Uint32x4:
            return GL_UNSIGNED_INT;
        case wgpu::VertexFormat::Sint32:
        case wgpu::VertexFormat::Sint32x2:
        case wgpu::VertexFormat::Sint32x3:
        case wgpu::VertexFormat::Sint32x4:
            return GL_INT;
        case wgpu::VertexFormat::Unorm10_10_10_2:
            return GL_UNSIGNED_INT_2_10_10_10_REV;
        default:
            DAWN_UNREACHABLE();
    }
}

GLboolean VertexFormatIsNormalized(wgpu::VertexFormat format) {
    switch (format) {
        case wgpu::VertexFormat::Unorm8x2:
        case wgpu::VertexFormat::Unorm8x4:
        case wgpu::VertexFormat::Snorm8x2:
        case wgpu::VertexFormat::Snorm8x4:
        case wgpu::VertexFormat::Unorm16x2:
        case wgpu::VertexFormat::Unorm16x4:
        case wgpu::VertexFormat::Snorm16x2:
        case wgpu::VertexFormat::Snorm16x4:
        case wgpu::VertexFormat::Unorm10_10_10_2:
            return GL_TRUE;
        default:
            return GL_FALSE;
    }
}

bool VertexFormatIsInt(wgpu::VertexFormat format) {
    switch (format) {
        case wgpu::VertexFormat::Uint8x2:
        case wgpu::VertexFormat::Uint8x4:
        case wgpu::VertexFormat::Sint8x2:
        case wgpu::VertexFormat::Sint8x4:
        case wgpu::VertexFormat::Uint16x2:
        case wgpu::VertexFormat::Uint16x4:
        case wgpu::VertexFormat::Sint16x2:
        case wgpu::VertexFormat::Sint16x4:
        case wgpu::VertexFormat::Uint32:
        case wgpu::VertexFormat::Uint32x2:
        case wgpu::VertexFormat::Uint32x3:
        case wgpu::VertexFormat::Uint32x4:
        case wgpu::VertexFormat::Sint32:
        case wgpu::VertexFormat::Sint32x2:
        case wgpu::VertexFormat::Sint32x3:
        case wgpu::VertexFormat::Sint32x4:
            return true;
        default:
            return false;
    }
}

// Vertex buffers and index buffers are implemented as part of an OpenGL VAO that
// corresponds to a VertexState. On the contrary in Dawn they are part of the global state.
// This means that we have to re-apply these buffers on a VertexState change.
class VertexStateBufferBindingTracker {
  public:
    void OnSetIndexBuffer(BufferBase* buffer) {
        mIndexBufferDirty = true;
        mIndexBuffer = ToBackend(buffer);
    }

    void OnSetVertexBuffer(VertexBufferSlot slot, BufferBase* buffer, uint64_t offset) {
        mVertexBuffers[slot] = ToBackend(buffer);
        mVertexBufferOffsets[slot] = offset;
        mDirtyVertexBuffers.set(slot);
    }

    void OnSetPipeline(RenderPipelineBase* pipeline) {
        if (mLastPipeline == pipeline) {
            return;
        }

        mIndexBufferDirty = true;
        mDirtyVertexBuffers |= pipeline->GetVertexBuffersUsed();

        mLastPipeline = pipeline;
    }

    void Apply(const OpenGLFunctions& gl, int32_t baseVertex, uint32_t firstInstance) {
        if (mBaseVertex != baseVertex) {
            mBaseVertex = baseVertex;
            mDirtyVertexBuffers |= mLastPipeline->GetVertexBuffersUsedAsVertexBuffer();
        }

        if (mFirstInstance != firstInstance) {
            mFirstInstance = firstInstance;
            mDirtyVertexBuffers |= mLastPipeline->GetVertexBuffersUsedAsInstanceBuffer();
        }

        if (mIndexBufferDirty && mIndexBuffer != nullptr) {
            gl.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->GetHandle());
            mIndexBufferDirty = false;
        }

        for (VertexBufferSlot slot :
             IterateBitSet(mDirtyVertexBuffers & mLastPipeline->GetVertexBuffersUsed())) {
            for (VertexAttributeLocation location :
                 IterateBitSet(ToBackend(mLastPipeline)->GetAttributesUsingVertexBuffer(slot))) {
                const VertexAttributeInfo& attribute = mLastPipeline->GetAttribute(location);

                GLuint attribIndex = static_cast<GLuint>(static_cast<uint8_t>(location));
                GLuint buffer = mVertexBuffers[slot]->GetHandle();
                intptr_t offset = mVertexBufferOffsets[slot];

                const VertexBufferInfo& vertexBuffer = mLastPipeline->GetVertexBuffer(slot);

                if (vertexBuffer.stepMode == wgpu::VertexStepMode::Vertex) {
                    offset += mBaseVertex * vertexBuffer.arrayStride;
                } else if (vertexBuffer.stepMode == wgpu::VertexStepMode::Instance) {
                    offset += mFirstInstance * vertexBuffer.arrayStride;
                }
                uint32_t components = GetVertexFormatInfo(attribute.format).componentCount;
                GLenum formatType = VertexFormatType(attribute.format);

                GLboolean normalized = VertexFormatIsNormalized(attribute.format);
                gl.BindBuffer(GL_ARRAY_BUFFER, buffer);
                if (VertexFormatIsInt(attribute.format)) {
                    gl.VertexAttribIPointer(
                        attribIndex, components, formatType, vertexBuffer.arrayStride,
                        reinterpret_cast<void*>(offset + static_cast<intptr_t>(attribute.offset)));
                } else {
                    gl.VertexAttribPointer(
                        attribIndex, components, formatType, normalized, vertexBuffer.arrayStride,
                        reinterpret_cast<void*>(offset + static_cast<intptr_t>(attribute.offset)));
                }
            }
        }

        mDirtyVertexBuffers.reset();
    }

  private:
    bool mIndexBufferDirty = false;
    raw_ptr<Buffer> mIndexBuffer = nullptr;

    VertexBufferMask mDirtyVertexBuffers;
    PerVertexBuffer<Buffer*> mVertexBuffers;
    PerVertexBuffer<uint64_t> mVertexBufferOffsets;

    int32_t mBaseVertex = 0;
    uint32_t mFirstInstance = 0;
    raw_ptr<RenderPipelineBase> mLastPipeline = nullptr;
};

class BindGroupTracker : public BindGroupTrackerBase<false, uint64_t> {
  public:
    void OnSetPipeline(RenderPipeline* pipeline) {
        BindGroupTrackerBase::OnSetPipeline(pipeline);
        mPipeline = pipeline;
        ResetInternalUniformDataDirtyRange();
    }

    void OnSetPipeline(ComputePipeline* pipeline) {
        BindGroupTrackerBase::OnSetPipeline(pipeline);
        mPipeline = pipeline;
        ResetInternalUniformDataDirtyRange();
    }

    void Apply(const OpenGLFunctions& gl) {
        BeforeApply();
        for (BindGroupIndex index : IterateBitSet(mDirtyBindGroupsObjectChangedOrIsDynamic)) {
            ApplyBindGroup(gl, index, mBindGroups[index], mDynamicOffsets[index]);
        }
        ApplyInternalUniforms(gl);
        AfterApply();
    }

  private:
    void BindSamplerAtIndex(const OpenGLFunctions& gl, SamplerBase* s, GLuint samplerIndex) {
        Sampler* sampler = ToBackend(s);

        for (PipelineGL::SamplerUnit unit : mPipeline->GetTextureUnitsForSampler(samplerIndex)) {
            // Only use filtering for certain texture units, because int
            // and uint texture are only complete without filtering
            if (unit.shouldUseFiltering) {
                gl.BindSampler(unit.unit, sampler->GetFilteringHandle());
            } else {
                gl.BindSampler(unit.unit, sampler->GetNonFilteringHandle());
            }
        }
    }

    void ApplyBindGroup(const OpenGLFunctions& gl,
                        BindGroupIndex groupIndex,
                        BindGroupBase* group,
                        const ityp::vector<BindingIndex, uint64_t>& dynamicOffsets) {
        const auto& indices = ToBackend(mPipelineLayout)->GetBindingIndexInfo()[groupIndex];

        for (BindingIndex bindingIndex{0}; bindingIndex < group->GetLayout()->GetBindingCount();
             ++bindingIndex) {
            const BindingInfo& bindingInfo = group->GetLayout()->GetBindingInfo(bindingIndex);
            MatchVariant(
                bindingInfo.bindingLayout,
                [&](const BufferBindingInfo& layout) {
                    BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex);
                    GLuint buffer = ToBackend(binding.buffer)->GetHandle();
                    GLuint index = indices[bindingIndex];
                    GLuint offset = binding.offset;

                    if (layout.hasDynamicOffset) {
                        // Dynamic buffers are packed at the front of BindingIndices.
                        offset += dynamicOffsets[bindingIndex];
                    }

                    GLenum target;
                    switch (layout.type) {
                        case wgpu::BufferBindingType::Uniform:
                            target = GL_UNIFORM_BUFFER;
                            break;
                        case wgpu::BufferBindingType::Storage:
                        case kInternalStorageBufferBinding:
                        case wgpu::BufferBindingType::ReadOnlyStorage:
                            target = GL_SHADER_STORAGE_BUFFER;
                            break;
                        case wgpu::BufferBindingType::Undefined:
                            DAWN_UNREACHABLE();
                    }

                    gl.BindBufferRange(target, index, buffer, offset, binding.size);
                },
                [&](const StaticSamplerBindingInfo& layout) {
                    BindSamplerAtIndex(gl, layout.sampler.Get(), indices[bindingIndex]);
                },
                [&](const SamplerBindingInfo&) {
                    BindSamplerAtIndex(gl, group->GetBindingAsSampler(bindingIndex),
                                       indices[bindingIndex]);
                },
                [&](const TextureBindingInfo&) {
                    TextureView* view = ToBackend(group->GetBindingAsTextureView(bindingIndex));
                    GLuint handle = view->GetHandle();
                    GLenum target = view->GetGLTarget();
                    GLuint viewIndex = indices[bindingIndex];

                    for (auto unit : mPipeline->GetTextureUnitsForTextureView(viewIndex)) {
                        gl.ActiveTexture(GL_TEXTURE0 + unit);
                        gl.BindTexture(target, handle);
                        if (ToBackend(view->GetTexture())->GetGLFormat().format ==
                            GL_DEPTH_STENCIL) {
                            Aspect aspect = view->GetAspects();
                            DAWN_ASSERT(HasOneBit(aspect));
                            switch (aspect) {
                                case Aspect::None:
                                case Aspect::Color:
                                case Aspect::CombinedDepthStencil:
                                case Aspect::Plane0:
                                case Aspect::Plane1:
                                case Aspect::Plane2:
                                    DAWN_UNREACHABLE();
                                case Aspect::Depth:
                                    gl.TexParameteri(target, GL_DEPTH_STENCIL_TEXTURE_MODE,
                                                     GL_DEPTH_COMPONENT);
                                    break;
                                case Aspect::Stencil:
                                    gl.TexParameteri(target, GL_DEPTH_STENCIL_TEXTURE_MODE,
                                                     GL_STENCIL_INDEX);
                                    break;
                            }
                        }
                        gl.TexParameteri(target, GL_TEXTURE_BASE_LEVEL, view->GetBaseMipLevel());
                        gl.TexParameteri(target, GL_TEXTURE_MAX_LEVEL,
                                         view->GetBaseMipLevel() + view->GetLevelCount() - 1);
                    }

                    // Some texture builtin function data needs emulation to update into the
                    // internal uniform buffer.
                    UpdateTextureBuiltinsUniformData(gl, view, groupIndex, bindingIndex);
                },
                [&](const StorageTextureBindingInfo& layout) {
                    TextureView* view = ToBackend(group->GetBindingAsTextureView(bindingIndex));
                    Texture* texture = ToBackend(view->GetTexture());
                    GLuint handle = texture->GetHandle();
                    GLuint imageIndex = indices[bindingIndex];

                    GLenum access;
                    switch (layout.access) {
                        case wgpu::StorageTextureAccess::WriteOnly:
                            access = GL_WRITE_ONLY;
                            break;
                        case wgpu::StorageTextureAccess::ReadWrite:
                            access = GL_READ_WRITE;
                            break;
                        case wgpu::StorageTextureAccess::ReadOnly:
                            access = GL_READ_ONLY;
                            break;
                        case wgpu::StorageTextureAccess::Undefined:
                            DAWN_UNREACHABLE();
                    }

                    // OpenGL ES only supports either binding a layer or the entire
                    // texture in glBindImageTexture().
                    GLboolean isLayered;
                    if (texture->GetArrayLayers() == view->GetLayerCount()) {
                        isLayered = GL_TRUE;
                    } else if (view->GetLayerCount() == 1) {
                        isLayered = GL_FALSE;
                    } else {
                        DAWN_UNREACHABLE();
                    }

                    gl.BindImageTexture(imageIndex, handle, view->GetBaseMipLevel(), isLayered,
                                        view->GetBaseArrayLayer(), access,
                                        texture->GetGLFormat().internalFormat);
                },
                [](const InputAttachmentBindingInfo&) { DAWN_UNREACHABLE(); });
        }
    }

    void UpdateTextureBuiltinsUniformData(const OpenGLFunctions& gl,
                                          const TextureView* view,
                                          BindGroupIndex groupIndex,
                                          BindingIndex bindingIndex) {
        const auto& bindingInfo = mPipeline->GetBindingPointBuiltinDataInfo();
        if (bindingInfo.empty()) {
            return;
        }

        auto iter = bindingInfo.find(tint::BindingPoint{static_cast<uint32_t>(groupIndex),
                                                        static_cast<uint32_t>(bindingIndex)});
        if (iter == bindingInfo.end()) {
            return;
        }

        // Update data by retrieving information from texture view object.
        const BindPointFunction field = iter->second.first;
        const size_t byteOffset = static_cast<size_t>(iter->second.second);

        uint32_t data;
        switch (field) {
            case BindPointFunction::kTextureNumLevels:
                data = view->GetLevelCount();
                break;
            case BindPointFunction::kTextureNumSamples:
                data = view->GetTexture()->GetSampleCount();
                break;
        }

        if (byteOffset >= mInternalUniformBufferData.size()) {
            mInternalUniformBufferData.resize(byteOffset + sizeof(uint32_t));
        }
        memcpy(mInternalUniformBufferData.data() + byteOffset, &data, sizeof(uint32_t));

        // Updating dirty range of the data vector
        mDirtyRange.first = std::min(mDirtyRange.first, byteOffset);
        mDirtyRange.second = std::max(mDirtyRange.second, byteOffset + sizeof(uint32_t));
    }

    void ResetInternalUniformDataDirtyRange() {
        mDirtyRange = {mInternalUniformBufferData.size(), 0};
    }

    void ApplyInternalUniforms(const OpenGLFunctions& gl) {
        const Buffer* internalUniformBuffer = mPipeline->GetInternalUniformBuffer();
        if (!internalUniformBuffer) {
            return;
        }

        GLuint internalUniformBufferHandle = internalUniformBuffer->GetHandle();
        if (mDirtyRange.first >= mDirtyRange.second) {
            // Early return if no dirty uniform range needs updating.
            return;
        }

        gl.BindBuffer(GL_UNIFORM_BUFFER, internalUniformBufferHandle);
        gl.BufferSubData(GL_UNIFORM_BUFFER, mDirtyRange.first,
                         mDirtyRange.second - mDirtyRange.first,
                         mInternalUniformBufferData.data() + mDirtyRange.first);
        gl.BindBuffer(GL_UNIFORM_BUFFER, 0);

        ResetInternalUniformDataDirtyRange();
    }

    raw_ptr<PipelineGL> mPipeline = nullptr;

    // The data used for mPipeline's internal uniform buffer from current bind group.
    // Expecting no more than 4 texture bindings called as textureNumLevels/textureNumSamples
    // argument in a pipeline. Initialize the vector to this size to avoid frequent resizing.
    std::vector<uint8_t> mInternalUniformBufferData = std::vector<uint8_t>(4 * sizeof(uint32_t));
    // Tracking dirty byte range of the mInternalUniformBufferData that needs to call bufferSubData
    // to update to the internal uniform buffer of mPipeline. Range it represents: [first, second)
    std::pair<size_t, size_t> mDirtyRange;
};

void ResolveMultisampledRenderTargets(const OpenGLFunctions& gl,
                                      const BeginRenderPassCmd* renderPass) {
    DAWN_ASSERT(renderPass != nullptr);

    GLuint readFbo = 0;
    GLuint writeFbo = 0;

    for (auto i : IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
        if (renderPass->colorAttachments[i].resolveTarget != nullptr) {
            if (readFbo == 0) {
                DAWN_ASSERT(writeFbo == 0);
                gl.GenFramebuffers(1, &readFbo);
                gl.GenFramebuffers(1, &writeFbo);
            }

            TextureView* colorView = ToBackend(renderPass->colorAttachments[i].view.Get());

            gl.BindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
            colorView->BindToFramebuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0);

            TextureView* resolveView =
                ToBackend(renderPass->colorAttachments[i].resolveTarget.Get());
            gl.BindFramebuffer(GL_DRAW_FRAMEBUFFER, writeFbo);
            resolveView->BindToFramebuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0);
            gl.BlitFramebuffer(0, 0, renderPass->width, renderPass->height, 0, 0, renderPass->width,
                               renderPass->height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
        }
    }

    gl.DeleteFramebuffers(1, &readFbo);
    gl.DeleteFramebuffers(1, &writeFbo);
}

// OpenGL SPEC requires the source/destination region must be a region that is contained
// within srcImage/dstImage. Here the size of the image refers to the virtual size, while
// Dawn validates texture copy extent with the physical size, so we need to re-calculate the
// texture copy extent to ensure it should fit in the virtual size of the subresource.
Extent3D ComputeTextureCopyExtent(const TextureCopy& textureCopy, const Extent3D& copySize) {
    Extent3D validTextureCopyExtent = copySize;
    const TextureBase* texture = textureCopy.texture.Get();
    Extent3D virtualSizeAtLevel =
        texture->GetMipLevelSingleSubresourceVirtualSize(textureCopy.mipLevel, textureCopy.aspect);
    DAWN_ASSERT(textureCopy.origin.x <= virtualSizeAtLevel.width);
    DAWN_ASSERT(textureCopy.origin.y <= virtualSizeAtLevel.height);
    if (copySize.width > virtualSizeAtLevel.width - textureCopy.origin.x) {
        DAWN_ASSERT(texture->GetFormat().isCompressed);
        validTextureCopyExtent.width = virtualSizeAtLevel.width - textureCopy.origin.x;
    }
    if (copySize.height > virtualSizeAtLevel.height - textureCopy.origin.y) {
        DAWN_ASSERT(texture->GetFormat().isCompressed);
        validTextureCopyExtent.height = virtualSizeAtLevel.height - textureCopy.origin.y;
    }

    return validTextureCopyExtent;
}

}  // namespace

CommandBuffer::CommandBuffer(CommandEncoder* encoder, const CommandBufferDescriptor* descriptor)
    : CommandBufferBase(encoder, descriptor) {}

MaybeError CommandBuffer::Execute() {
    const OpenGLFunctions& gl = ToBackend(GetDevice())->GetGL();

    auto LazyClearSyncScope = [](const SyncScopeResourceUsage& scope) -> MaybeError {
        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.
            DAWN_TRY(scope.textureSyncInfos[i].Iterate(
                [&](const SubresourceRange& range, const TextureSyncInfo& syncInfo) -> MaybeError {
                    if (syncInfo.usage & ~wgpu::TextureUsage::RenderAttachment) {
                        DAWN_TRY(texture->EnsureSubresourceContentInitialized(range));
                    }
                    return {};
                }));
        }

        for (BufferBase* bufferBase : scope.buffers) {
            ToBackend(bufferBase)->EnsureDataInitialized();
        }
        return {};
    };

    size_t nextComputePassNumber = 0;
    size_t nextRenderPassNumber = 0;

    Command type;
    while (mCommands.NextCommandId(&type)) {
        switch (type) {
            case Command::BeginComputePass: {
                mCommands.NextCommand<BeginComputePassCmd>();
                for (const SyncScopeResourceUsage& scope :
                     GetResourceUsages().computePasses[nextComputePassNumber].dispatchUsages) {
                    DAWN_TRY(LazyClearSyncScope(scope));
                }
                DAWN_TRY(ExecuteComputePass());

                nextComputePassNumber++;
                break;
            }

            case Command::BeginRenderPass: {
                auto* cmd = mCommands.NextCommand<BeginRenderPassCmd>();
                DAWN_TRY(
                    LazyClearSyncScope(GetResourceUsages().renderPasses[nextRenderPassNumber]));
                LazyClearRenderPassAttachments(cmd);
                DAWN_TRY(ExecuteRenderPass(cmd));

                nextRenderPassNumber++;
                break;
            }

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

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

                gl.BindBuffer(GL_PIXEL_PACK_BUFFER, ToBackend(copy->source)->GetHandle());
                gl.BindBuffer(GL_PIXEL_UNPACK_BUFFER, ToBackend(copy->destination)->GetHandle());
                gl.CopyBufferSubData(GL_PIXEL_PACK_BUFFER, GL_PIXEL_UNPACK_BUFFER,
                                     copy->sourceOffset, copy->destinationOffset, copy->size);

                gl.BindBuffer(GL_PIXEL_PACK_BUFFER, 0);
                gl.BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);

                ToBackend(copy->source)->TrackUsage();
                ToBackend(copy->destination)->TrackUsage();
                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;
                Buffer* buffer = ToBackend(src.buffer.Get());

                buffer->EnsureDataInitialized();
                SubresourceRange range = GetSubresourcesAffectedByCopy(dst, copy->copySize);
                if (IsCompleteSubresourceCopiedTo(dst.texture.Get(), copy->copySize, dst.mipLevel,
                                                  dst.aspect)) {
                    dst.texture->SetIsSubresourceContentInitialized(true, range);
                } else {
                    DAWN_TRY(ToBackend(dst.texture)->EnsureSubresourceContentInitialized(range));
                }

                gl.BindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer->GetHandle());

                TextureDataLayout dataLayout;
                dataLayout.offset = 0;
                dataLayout.bytesPerRow = src.bytesPerRow;
                dataLayout.rowsPerImage = src.rowsPerImage;

                DoTexSubImage(gl, dst, reinterpret_cast<void*>(src.offset), dataLayout,
                              copy->copySize);
                gl.BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);

                buffer->TrackUsage();
                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());
                const Format& formatInfo = texture->GetFormat();
                const GLFormat& format = texture->GetGLFormat();
                GLenum target = texture->GetGLTarget();

                if (formatInfo.isCompressed) {
                    DAWN_UNREACHABLE();
                }

                buffer->EnsureDataInitializedAsDestination(copy);

                SubresourceRange subresources = GetSubresourcesAffectedByCopy(src, copy->copySize);
                DAWN_TRY(texture->EnsureSubresourceContentInitialized(subresources));
                // The only way to move data from a texture to a buffer in GL is via
                // glReadPixels with a pack buffer. Create a temporary FBO for the copy.
                gl.BindTexture(target, texture->GetHandle());

                GLuint readFBO = 0;
                gl.GenFramebuffers(1, &readFBO);
                gl.BindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);

                const TexelBlockInfo& blockInfo = formatInfo.GetAspectInfo(src.aspect).block;

                gl.BindBuffer(GL_PIXEL_PACK_BUFFER, buffer->GetHandle());
                gl.PixelStorei(GL_PACK_ALIGNMENT, std::min(8u, blockInfo.byteSize));
                gl.PixelStorei(GL_PACK_ROW_LENGTH, dst.bytesPerRow / blockInfo.byteSize);

                GLenum glAttachment;
                GLenum glFormat;
                GLenum glType;
                switch (src.aspect) {
                    case Aspect::Color:
                        glAttachment = GL_COLOR_ATTACHMENT0;
                        glFormat = format.format;
                        glType = format.type;
                        break;
                    case Aspect::Depth:
                        glAttachment = GL_DEPTH_ATTACHMENT;
                        glFormat = GL_DEPTH_COMPONENT;
                        glType = GL_FLOAT;
                        break;
                    case Aspect::Stencil:
                        glAttachment = GL_STENCIL_ATTACHMENT;
                        glFormat = GL_STENCIL_INDEX;
                        glType = GL_UNSIGNED_BYTE;
                        break;

                    case Aspect::CombinedDepthStencil:
                    case Aspect::None:
                    case Aspect::Plane0:
                    case Aspect::Plane1:
                    case Aspect::Plane2:
                        DAWN_UNREACHABLE();
                }

                uint8_t* offset = reinterpret_cast<uint8_t*>(static_cast<uintptr_t>(dst.offset));
                switch (texture->GetDimension()) {
                    case wgpu::TextureDimension::Undefined:
                        DAWN_UNREACHABLE();
                    case wgpu::TextureDimension::e1D:
                    case wgpu::TextureDimension::e2D: {
                        if (target == GL_TEXTURE_2D) {
                            DAWN_ASSERT(texture->GetArrayLayers() == 1);
                            gl.FramebufferTexture2D(GL_READ_FRAMEBUFFER, glAttachment, target,
                                                    texture->GetHandle(), src.mipLevel);
                            gl.ReadPixels(src.origin.x, src.origin.y, copySize.width,
                                          copySize.height, glFormat, glType, offset);
                            break;
                        } else if (target == GL_TEXTURE_CUBE_MAP) {
                            DAWN_ASSERT(texture->GetArrayLayers() == 6);
                            const uint64_t bytesPerImage = dst.bytesPerRow * dst.rowsPerImage;
                            for (uint32_t z = 0; z < copySize.depthOrArrayLayers; ++z) {
                                GLenum cubeMapTarget =
                                    GL_TEXTURE_CUBE_MAP_POSITIVE_X + z + src.origin.z;
                                gl.FramebufferTexture2D(GL_READ_FRAMEBUFFER, glAttachment,
                                                        cubeMapTarget, texture->GetHandle(),
                                                        src.mipLevel);
                                gl.ReadPixels(src.origin.x, src.origin.y, copySize.width,
                                              copySize.height, glFormat, glType, offset);
                                offset += bytesPerImage;
                            }
                            break;
                        }
                        // Implementation for 2D array is the same as 3D.
                        [[fallthrough]];
                    }

                    case wgpu::TextureDimension::e3D: {
                        const uint64_t bytesPerImage = dst.bytesPerRow * dst.rowsPerImage;
                        for (uint32_t z = 0; z < copySize.depthOrArrayLayers; ++z) {
                            gl.FramebufferTextureLayer(GL_READ_FRAMEBUFFER, glAttachment,
                                                       texture->GetHandle(), src.mipLevel,
                                                       src.origin.z + z);
                            gl.ReadPixels(src.origin.x, src.origin.y, copySize.width,
                                          copySize.height, glFormat, glType, offset);

                            offset += bytesPerImage;
                        }
                        break;
                    }
                }

                gl.PixelStorei(GL_PACK_ROW_LENGTH, 0);
                gl.PixelStorei(GL_PACK_ALIGNMENT, 4);  // Reset to default
                gl.BindBuffer(GL_PIXEL_PACK_BUFFER, 0);
                gl.DeleteFramebuffers(1, &readFBO);

                buffer->TrackUsage();
                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;
                }
                auto& src = copy->source;
                auto& dst = copy->destination;

                // TODO(crbug.com/dawn/817): add workaround for the case that imageExtentSrc
                // is not equal to imageExtentDst. For example when copySize fits in the virtual
                // size of the source image but does not fit in the one of the destination
                // image.
                Extent3D copySize = ComputeTextureCopyExtent(dst, copy->copySize);
                Texture* srcTexture = ToBackend(src.texture.Get());
                Texture* dstTexture = ToBackend(dst.texture.Get());

                SubresourceRange srcRange = GetSubresourcesAffectedByCopy(src, copy->copySize);
                SubresourceRange dstRange = GetSubresourcesAffectedByCopy(dst, copy->copySize);

                DAWN_TRY(srcTexture->EnsureSubresourceContentInitialized(srcRange));
                if (IsCompleteSubresourceCopiedTo(dstTexture, copySize, dst.mipLevel, dst.aspect)) {
                    dstTexture->SetIsSubresourceContentInitialized(true, dstRange);
                } else {
                    DAWN_TRY(dstTexture->EnsureSubresourceContentInitialized(dstRange));
                }
                CopyImageSubData(gl, src.aspect, srcTexture->GetHandle(), srcTexture->GetGLTarget(),
                                 src.mipLevel, src.origin, dstTexture->GetHandle(),
                                 dstTexture->GetGLTarget(), dst.mipLevel, dst.origin, copySize);
                break;
            }

            case Command::ClearBuffer: {
                ClearBufferCmd* cmd = mCommands.NextCommand<ClearBufferCmd>();
                if (cmd->size == 0) {
                    // Skip no-op fills.
                    break;
                }
                Buffer* dstBuffer = ToBackend(cmd->buffer.Get());

                bool clearedToZero =
                    dstBuffer->EnsureDataInitializedAsDestination(cmd->offset, cmd->size);

                if (!clearedToZero) {
                    const std::vector<uint8_t> clearValues(cmd->size, 0u);
                    gl.BindBuffer(GL_ARRAY_BUFFER, dstBuffer->GetHandle());
                    gl.BufferSubData(GL_ARRAY_BUFFER, cmd->offset, cmd->size, clearValues.data());
                }

                dstBuffer->TrackUsage();
                break;
            }

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

                size_t size = cmd->queryCount * sizeof(uint64_t);
                destination->EnsureDataInitializedAsDestination(cmd->destinationOffset, size);

                std::vector<uint64_t> values(cmd->queryCount);
                auto availability = querySet->GetQueryAvailability();

                for (uint32_t i = 0; i < cmd->queryCount; ++i) {
                    if (!availability[cmd->firstQuery + i]) {
                        values[i] = 0;
                        continue;
                    }
                    uint32_t query = querySet->Get(cmd->firstQuery + i);
                    GLuint value;
                    gl.GetQueryObjectuiv(query, GL_QUERY_RESULT, &value);
                    values[i] = value;
                }

                gl.BindBuffer(GL_ARRAY_BUFFER, destination->GetHandle());
                gl.BufferSubData(GL_ARRAY_BUFFER, cmd->destinationOffset, size, values.data());

                break;
            }

            case Command::WriteTimestamp: {
                return DAWN_UNIMPLEMENTED_ERROR("WriteTimestamp unimplemented");
            }

            case Command::InsertDebugMarker:
            case Command::PopDebugGroup:
            case Command::PushDebugGroup: {
                // Due to lack of linux driver support for GL_EXT_debug_marker
                // extension these functions are skipped.
                SkipCommand(&mCommands, type);
                break;
            }

            case Command::WriteBuffer: {
                WriteBufferCmd* write = mCommands.NextCommand<WriteBufferCmd>();
                uint64_t offset = write->offset;
                uint64_t size = write->size;
                if (size == 0) {
                    continue;
                }

                Buffer* dstBuffer = ToBackend(write->buffer.Get());
                uint8_t* data = mCommands.NextData<uint8_t>(size);
                dstBuffer->EnsureDataInitializedAsDestination(offset, size);

                gl.BindBuffer(GL_ARRAY_BUFFER, dstBuffer->GetHandle());
                gl.BufferSubData(GL_ARRAY_BUFFER, offset, size, data);

                dstBuffer->TrackUsage();
                break;
            }

            default:
                DAWN_UNREACHABLE();
        }
    }

    return {};
}

MaybeError CommandBuffer::ExecuteComputePass() {
    const OpenGLFunctions& gl = ToBackend(GetDevice())->GetGL();
    ComputePipeline* lastPipeline = nullptr;
    BindGroupTracker bindGroupTracker = {};

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

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

                gl.DispatchCompute(dispatch->x, dispatch->y, dispatch->z);
                gl.MemoryBarrier(GL_ALL_BARRIER_BITS);
                break;
            }

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

                uint64_t indirectBufferOffset = dispatch->indirectOffset;
                Buffer* indirectBuffer = ToBackend(dispatch->indirectBuffer.Get());

                gl.BindBuffer(GL_DISPATCH_INDIRECT_BUFFER, indirectBuffer->GetHandle());
                gl.DispatchComputeIndirect(static_cast<GLintptr>(indirectBufferOffset));
                gl.MemoryBarrier(GL_ALL_BARRIER_BITS);

                indirectBuffer->TrackUsage();
                break;
            }

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

                bindGroupTracker.OnSetPipeline(lastPipeline);
                break;
            }

            case Command::SetBindGroup: {
                SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>();
                uint32_t* dynamicOffsets = nullptr;
                if (cmd->dynamicOffsetCount > 0) {
                    dynamicOffsets = mCommands.NextData<uint32_t>(cmd->dynamicOffsetCount);
                }
                bindGroupTracker.OnSetBindGroup(cmd->index, cmd->group.Get(),
                                                cmd->dynamicOffsetCount, dynamicOffsets);
                break;
            }

            case Command::InsertDebugMarker:
            case Command::PopDebugGroup:
            case Command::PushDebugGroup: {
                // Due to lack of linux driver support for GL_EXT_debug_marker
                // extension these functions are skipped.
                SkipCommand(&mCommands, type);
                break;
            }

            case Command::WriteTimestamp: {
                return DAWN_UNIMPLEMENTED_ERROR("WriteTimestamp unimplemented");
            }

            default:
                DAWN_UNREACHABLE();
        }
    }

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

MaybeError CommandBuffer::ExecuteRenderPass(BeginRenderPassCmd* renderPass) {
    const OpenGLFunctions& gl = ToBackend(GetDevice())->GetGL();
    GLuint fbo = 0;

    // Create the framebuffer used for this render pass and calls the correct glDrawBuffers
    {
        // TODO(kainino@chromium.org): This is added to possibly work around an issue seen on
        // Windows/Intel. It should break any feedback loop before the clears, even if there
        // shouldn't be any negative effects from this. Investigate whether it's actually
        // needed.
        gl.BindFramebuffer(GL_READ_FRAMEBUFFER, 0);
        // TODO(kainino@chromium.org): possible future optimization: create these framebuffers
        // at Framebuffer build time (or maybe CommandBuffer build time) so they don't have to
        // be created and destroyed at draw time.
        gl.GenFramebuffers(1, &fbo);
        gl.BindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);

        // Mapping from attachmentSlot to GL framebuffer attachment points. Defaults to zero
        // (GL_NONE).
        PerColorAttachment<GLenum> drawBuffers = {};

        // Construct GL framebuffer

        ColorAttachmentIndex attachmentCount{};
        for (auto i : IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
            TextureView* textureView = ToBackend(renderPass->colorAttachments[i].view.Get());
            GLenum glAttachment = GL_COLOR_ATTACHMENT0 + static_cast<uint8_t>(i);

            // Attach color buffers.
            textureView->BindToFramebuffer(GL_DRAW_FRAMEBUFFER, glAttachment,
                                           renderPass->colorAttachments[i].depthSlice);
            drawBuffers[i] = glAttachment;
            attachmentCount = ityp::PlusOne(i);
        }
        gl.DrawBuffers(static_cast<uint8_t>(attachmentCount), drawBuffers.data());

        if (renderPass->attachmentState->HasDepthStencilAttachment()) {
            TextureView* textureView = ToBackend(renderPass->depthStencilAttachment.view.Get());
            const Format& format = textureView->GetTexture()->GetFormat();

            // Attach depth/stencil buffer.
            GLenum glAttachment = 0;
            if (format.aspects == (Aspect::Depth | Aspect::Stencil)) {
                glAttachment = GL_DEPTH_STENCIL_ATTACHMENT;
            } else if (format.aspects == Aspect::Depth) {
                glAttachment = GL_DEPTH_ATTACHMENT;
            } else if (format.aspects == Aspect::Stencil) {
                glAttachment = GL_STENCIL_ATTACHMENT;
            } else {
                DAWN_UNREACHABLE();
            }

            textureView->BindToFramebuffer(GL_DRAW_FRAMEBUFFER, glAttachment);
        }
    }

    DAWN_ASSERT(gl.CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);

    // Set defaults for dynamic state before executing clears and commands.
    PersistentPipelineState persistentPipelineState;
    persistentPipelineState.SetDefaultState(gl);
    gl.BlendColor(0, 0, 0, 0);
    gl.Viewport(0, 0, renderPass->width, renderPass->height);
    float minDepth = 0.0f;
    float maxDepth = 1.0f;
    gl.DepthRangef(minDepth, maxDepth);

    gl.Scissor(0, 0, renderPass->width, renderPass->height);

    // Clear framebuffer attachments as needed
    {
        for (auto index : IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
            uint8_t i = static_cast<uint8_t>(index);
            auto* attachmentInfo = &renderPass->colorAttachments[index];

            // Load op - color
            if (attachmentInfo->loadOp == wgpu::LoadOp::Clear) {
                gl.ColorMask(true, true, true, true);

                TextureComponentType baseType =
                    attachmentInfo->view->GetFormat().GetAspectInfo(Aspect::Color).baseType;
                switch (baseType) {
                    case TextureComponentType::Float: {
                        const std::array<float, 4> appliedClearColor =
                            ConvertToFloatColor(attachmentInfo->clearColor);
                        gl.ClearBufferfv(GL_COLOR, i, appliedClearColor.data());
                        break;
                    }
                    case TextureComponentType::Uint: {
                        const std::array<uint32_t, 4> appliedClearColor =
                            ConvertToUnsignedIntegerColor(attachmentInfo->clearColor);
                        gl.ClearBufferuiv(GL_COLOR, i, appliedClearColor.data());
                        break;
                    }
                    case TextureComponentType::Sint: {
                        const std::array<int32_t, 4> appliedClearColor =
                            ConvertToSignedIntegerColor(attachmentInfo->clearColor);
                        gl.ClearBufferiv(GL_COLOR, i, appliedClearColor.data());
                        break;
                    }
                }
            }

            if (attachmentInfo->storeOp == wgpu::StoreOp::Discard) {
                // TODO(natlee@microsoft.com): call glDiscard to do optimization
            }
        }

        if (renderPass->attachmentState->HasDepthStencilAttachment()) {
            auto* attachmentInfo = &renderPass->depthStencilAttachment;
            const Format& attachmentFormat = attachmentInfo->view->GetTexture()->GetFormat();

            // Load op - depth/stencil
            bool doDepthClear =
                attachmentFormat.HasDepth() && (attachmentInfo->depthLoadOp == wgpu::LoadOp::Clear);
            bool doStencilClear = attachmentFormat.HasStencil() &&
                                  (attachmentInfo->stencilLoadOp == wgpu::LoadOp::Clear);

            if (doDepthClear) {
                gl.DepthMask(GL_TRUE);
            }
            if (doStencilClear) {
                gl.StencilMask(GetStencilMaskFromStencilFormat(attachmentFormat.format));
            }

            if (doDepthClear && doStencilClear) {
                gl.ClearBufferfi(GL_DEPTH_STENCIL, 0, attachmentInfo->clearDepth,
                                 attachmentInfo->clearStencil);
            } else if (doDepthClear) {
                gl.ClearBufferfv(GL_DEPTH, 0, &attachmentInfo->clearDepth);
            } else if (doStencilClear) {
                const GLint clearStencil = attachmentInfo->clearStencil;
                gl.ClearBufferiv(GL_STENCIL, 0, &clearStencil);
            }
        }
    }

    RenderPipeline* lastPipeline = nullptr;
    uint64_t indexBufferBaseOffset = 0;
    GLenum indexBufferFormat;
    uint32_t indexFormatSize;

    VertexStateBufferBindingTracker vertexStateBufferBindingTracker;
    BindGroupTracker bindGroupTracker = {};

    auto DoRenderBundleCommand = [&](CommandIterator* iter, Command type) {
        switch (type) {
            case Command::Draw: {
                DrawCmd* draw = iter->NextCommand<DrawCmd>();
                vertexStateBufferBindingTracker.Apply(gl, 0, draw->firstInstance);
                bindGroupTracker.Apply(gl);

                if (lastPipeline->UsesInstanceIndex()) {
                    gl.Uniform1ui(PipelineLayout::PushConstantLocation::FirstInstance,
                                  draw->firstInstance);
                }
                gl.DrawArraysInstanced(lastPipeline->GetGLPrimitiveTopology(), draw->firstVertex,
                                       draw->vertexCount, draw->instanceCount);
                break;
            }

            case Command::DrawIndexed: {
                DrawIndexedCmd* draw = iter->NextCommand<DrawIndexedCmd>();
                vertexStateBufferBindingTracker.Apply(gl, draw->baseVertex, draw->firstInstance);
                bindGroupTracker.Apply(gl);

                const auto topology = lastPipeline->GetGLPrimitiveTopology();
                if (topology == GL_LINE_STRIP || topology == GL_TRIANGLE_STRIP) {
                    gl.Enable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
                } else {
                    gl.Disable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
                }

                if (lastPipeline->UsesVertexIndex()) {
                    gl.Uniform1ui(PipelineLayout::PushConstantLocation::FirstVertex,
                                  draw->baseVertex);
                }
                if (lastPipeline->UsesInstanceIndex()) {
                    gl.Uniform1ui(PipelineLayout::PushConstantLocation::FirstInstance,
                                  draw->firstInstance);
                }
                gl.DrawElementsInstanced(
                    topology, draw->indexCount, indexBufferFormat,
                    reinterpret_cast<void*>(draw->firstIndex * indexFormatSize +
                                            indexBufferBaseOffset),
                    draw->instanceCount);
                break;
            }

            case Command::DrawIndirect: {
                DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>();
                if (lastPipeline->UsesInstanceIndex()) {
                    gl.Uniform1ui(PipelineLayout::PushConstantLocation::FirstInstance, 0);
                }
                vertexStateBufferBindingTracker.Apply(gl, 0, 0);
                bindGroupTracker.Apply(gl);

                uint64_t indirectBufferOffset = draw->indirectOffset;
                Buffer* indirectBuffer = ToBackend(draw->indirectBuffer.Get());

                gl.BindBuffer(GL_DRAW_INDIRECT_BUFFER, indirectBuffer->GetHandle());
                gl.DrawArraysIndirect(
                    lastPipeline->GetGLPrimitiveTopology(),
                    reinterpret_cast<void*>(static_cast<intptr_t>(indirectBufferOffset)));
                indirectBuffer->TrackUsage();
                break;
            }

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

                if (lastPipeline->UsesInstanceIndex()) {
                    gl.Uniform1ui(PipelineLayout::PushConstantLocation::FirstInstance, 0);
                }
                vertexStateBufferBindingTracker.Apply(gl, 0, 0);
                bindGroupTracker.Apply(gl);

                Buffer* indirectBuffer = ToBackend(draw->indirectBuffer.Get());
                DAWN_ASSERT(indirectBuffer != nullptr);

                const auto topology = lastPipeline->GetGLPrimitiveTopology();
                if (topology == GL_LINE_STRIP || topology == GL_TRIANGLE_STRIP) {
                    gl.Enable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
                } else {
                    gl.Disable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
                }

                gl.BindBuffer(GL_DRAW_INDIRECT_BUFFER, indirectBuffer->GetHandle());
                gl.DrawElementsIndirect(
                    topology, indexBufferFormat,
                    reinterpret_cast<void*>(static_cast<intptr_t>(draw->indirectOffset)));
                indirectBuffer->TrackUsage();
                break;
            }

            case Command::InsertDebugMarker:
            case Command::PopDebugGroup:
            case Command::PushDebugGroup: {
                // Due to lack of linux driver support for GL_EXT_debug_marker
                // extension these functions are skipped.
                SkipCommand(iter, type);
                break;
            }

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

                vertexStateBufferBindingTracker.OnSetPipeline(lastPipeline);
                bindGroupTracker.OnSetPipeline(lastPipeline);
                if (lastPipeline->UsesFragDepth()) {
                    gl.Uniform1f(PipelineLayout::PushConstantLocation::MinDepth, minDepth);
                    gl.Uniform1f(PipelineLayout::PushConstantLocation::MaxDepth, maxDepth);
                }
                break;
            }

            case Command::SetBindGroup: {
                SetBindGroupCmd* cmd = iter->NextCommand<SetBindGroupCmd>();
                uint32_t* dynamicOffsets = nullptr;
                if (cmd->dynamicOffsetCount > 0) {
                    dynamicOffsets = iter->NextData<uint32_t>(cmd->dynamicOffsetCount);
                }
                bindGroupTracker.OnSetBindGroup(cmd->index, cmd->group.Get(),
                                                cmd->dynamicOffsetCount, dynamicOffsets);
                break;
            }

            case Command::SetIndexBuffer: {
                SetIndexBufferCmd* cmd = iter->NextCommand<SetIndexBufferCmd>();

                indexBufferBaseOffset = cmd->offset;
                indexBufferFormat = IndexFormatType(cmd->format);
                indexFormatSize = IndexFormatSize(cmd->format);
                vertexStateBufferBindingTracker.OnSetIndexBuffer(cmd->buffer.Get());
                ToBackend(cmd->buffer)->TrackUsage();
                break;
            }

            case Command::SetVertexBuffer: {
                SetVertexBufferCmd* cmd = iter->NextCommand<SetVertexBufferCmd>();
                vertexStateBufferBindingTracker.OnSetVertexBuffer(cmd->slot, cmd->buffer.Get(),
                                                                  cmd->offset);
                ToBackend(cmd->buffer)->TrackUsage();
                break;
            }

            default:
                DAWN_UNREACHABLE();
                break;
        }
    };

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

                if (renderPass->attachmentState->GetSampleCount() > 1) {
                    ResolveMultisampledRenderTargets(gl, renderPass);
                }
                gl.DeleteFramebuffers(1, &fbo);
                return {};
            }

            case Command::SetStencilReference: {
                SetStencilReferenceCmd* cmd = mCommands.NextCommand<SetStencilReferenceCmd>();
                persistentPipelineState.SetStencilReference(gl, cmd->reference);
                break;
            }

            case Command::SetViewport: {
                SetViewportCmd* cmd = mCommands.NextCommand<SetViewportCmd>();
                if (gl.IsAtLeastGL(4, 1)) {
                    gl.ViewportIndexedf(0, cmd->x, cmd->y, cmd->width, cmd->height);
                } else {
                    // Floating-point viewport coords are unsupported on OpenGL ES, but
                    // truncation is ok because other APIs do not guarantee subpixel precision
                    // either.
                    gl.Viewport(static_cast<int>(cmd->x), static_cast<int>(cmd->y),
                                static_cast<int>(cmd->width), static_cast<int>(cmd->height));
                }
                minDepth = cmd->minDepth;
                maxDepth = cmd->maxDepth;
                gl.DepthRangef(minDepth, maxDepth);
                if (lastPipeline && lastPipeline->UsesFragDepth()) {
                    gl.Uniform1f(PipelineLayout::PushConstantLocation::MinDepth, minDepth);
                    gl.Uniform1f(PipelineLayout::PushConstantLocation::MaxDepth, maxDepth);
                }
                break;
            }

            case Command::SetScissorRect: {
                SetScissorRectCmd* cmd = mCommands.NextCommand<SetScissorRectCmd>();
                gl.Scissor(cmd->x, cmd->y, cmd->width, cmd->height);
                break;
            }

            case Command::SetBlendConstant: {
                SetBlendConstantCmd* cmd = mCommands.NextCommand<SetBlendConstantCmd>();
                const std::array<float, 4> blendColor = ConvertToFloatColor(cmd->color);
                gl.BlendColor(blendColor[0], blendColor[1], blendColor[2], blendColor[3]);
                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)) {
                        DoRenderBundleCommand(iter, type);
                    }
                }
                break;
            }

            case Command::BeginOcclusionQuery: {
                BeginOcclusionQueryCmd* cmd = mCommands.NextCommand<BeginOcclusionQueryCmd>();
                QuerySet* querySet = ToBackend(renderPass->occlusionQuerySet.Get());
                gl.BeginQuery(GL_ANY_SAMPLES_PASSED, querySet->Get(cmd->queryIndex));
                break;
            }

            case Command::EndOcclusionQuery: {
                mCommands.NextCommand<EndOcclusionQueryCmd>();
                gl.EndQuery(GL_ANY_SAMPLES_PASSED);
                break;
            }

            case Command::WriteTimestamp:
                return DAWN_UNIMPLEMENTED_ERROR("WriteTimestamp unimplemented");

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

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

void DoTexSubImage(const OpenGLFunctions& gl,
                   const TextureCopy& destination,
                   const void* data,
                   const TextureDataLayout& dataLayout,
                   const Extent3D& copySize) {
    Texture* texture = ToBackend(destination.texture.Get());

    const GLFormat& format = texture->GetGLFormat();
    GLenum target = texture->GetGLTarget();
    data = static_cast<const uint8_t*>(data) + dataLayout.offset;
    gl.ActiveTexture(GL_TEXTURE0);
    gl.BindTexture(target, texture->GetHandle());
    const TexelBlockInfo& blockInfo = texture->GetFormat().GetAspectInfo(destination.aspect).block;

    uint32_t x = destination.origin.x;
    uint32_t y = destination.origin.y;
    uint32_t z = destination.origin.z;
    if (texture->GetFormat().isCompressed) {
        size_t rowSize = copySize.width / blockInfo.width * blockInfo.byteSize;
        Extent3D virtSize = texture->GetMipLevelSingleSubresourceVirtualSize(destination.mipLevel,
                                                                             destination.aspect);
        uint32_t width = std::min(copySize.width, virtSize.width - x);

        // In GLES glPixelStorei() doesn't affect CompressedTexSubImage*D() and
        // GL_UNPACK_COMPRESSED_BLOCK_* isn't defined, so we have to workaround
        // this limitation by copying the compressed texture data once per row.
        // See OpenGL ES 3.2 SPEC Chapter 8.4.1, "Pixel Storage Modes and Pixel
        // Buffer Objects" for more details. For Desktop GL, we use row-by-row
        // copies only for uploads where bytesPerRow is not a multiple of byteSize.
        if (dataLayout.bytesPerRow % blockInfo.byteSize == 0 && gl.GetVersion().IsDesktop()) {
            size_t imageSize =
                rowSize * (copySize.height / blockInfo.height) * copySize.depthOrArrayLayers;

            uint32_t height = std::min(copySize.height, virtSize.height - y);

            gl.PixelStorei(GL_UNPACK_ROW_LENGTH,
                           dataLayout.bytesPerRow / blockInfo.byteSize * blockInfo.width);
            gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_SIZE, blockInfo.byteSize);
            gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_WIDTH, blockInfo.width);
            gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_HEIGHT, blockInfo.height);
            gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_DEPTH, 1);

            if (target == GL_TEXTURE_2D) {
                gl.CompressedTexSubImage2D(target, destination.mipLevel, x, y, width, height,
                                           format.internalFormat, imageSize, data);
            } else if (target == GL_TEXTURE_CUBE_MAP) {
                DAWN_ASSERT(texture->GetArrayLayers() == 6);
                const uint8_t* pointer = static_cast<const uint8_t*>(data);
                uint32_t baseLayer = destination.origin.z;
                for (uint32_t l = 0; l < copySize.depthOrArrayLayers; ++l) {
                    GLenum cubeMapTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + baseLayer + l;
                    gl.CompressedTexSubImage2D(cubeMapTarget, destination.mipLevel, x, y, width,
                                               height, format.internalFormat, imageSize, pointer);
                    pointer += dataLayout.rowsPerImage * dataLayout.bytesPerRow;
                }
            } else {
                gl.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, dataLayout.rowsPerImage * blockInfo.height);
                gl.CompressedTexSubImage3D(target, destination.mipLevel, x, y, z, width, height,
                                           copySize.depthOrArrayLayers, format.internalFormat,
                                           imageSize, data);
                gl.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
            }

            gl.PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
            gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_SIZE, 0);
            gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_WIDTH, 0);
            gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_HEIGHT, 0);
            gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_DEPTH, 0);
        } else {
            if (target == GL_TEXTURE_2D) {
                const uint8_t* d = static_cast<const uint8_t*>(data);

                for (; y < destination.origin.y + copySize.height; y += blockInfo.height) {
                    uint32_t height = std::min(blockInfo.height, virtSize.height - y);
                    gl.CompressedTexSubImage2D(target, destination.mipLevel, x, y, width, height,
                                               format.internalFormat, rowSize, d);
                    d += dataLayout.bytesPerRow;
                }
            } else if (target == GL_TEXTURE_CUBE_MAP) {
                DAWN_ASSERT(texture->GetArrayLayers() == 6);
                const uint8_t* pointer = static_cast<const uint8_t*>(data);
                uint32_t baseLayer = destination.origin.z;
                for (uint32_t l = 0; l < copySize.depthOrArrayLayers; ++l) {
                    const uint8_t* d =
                        pointer + l * dataLayout.rowsPerImage * dataLayout.bytesPerRow;
                    GLenum cubeMapTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + baseLayer + l;
                    for (y = destination.origin.y; y < destination.origin.y + copySize.height;
                         y += blockInfo.height) {
                        uint32_t height = std::min(blockInfo.height, virtSize.height - y);
                        gl.CompressedTexSubImage2D(cubeMapTarget, destination.mipLevel, x, y, width,
                                                   height, format.internalFormat, rowSize, d);
                        d += dataLayout.bytesPerRow;
                    }
                }
            } else {
                DAWN_ASSERT(target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY ||
                            target == GL_TEXTURE_CUBE_MAP_ARRAY);
                const uint8_t* slice = static_cast<const uint8_t*>(data);

                for (; z < destination.origin.z + copySize.depthOrArrayLayers; ++z) {
                    const uint8_t* d = slice;

                    for (y = destination.origin.y; y < destination.origin.y + copySize.height;
                         y += blockInfo.height) {
                        uint32_t height = std::min(blockInfo.height, virtSize.height - y);
                        gl.CompressedTexSubImage3D(target, destination.mipLevel, x, y, z, width,
                                                   height, 1, format.internalFormat, rowSize, d);
                        d += dataLayout.bytesPerRow;
                    }

                    slice += dataLayout.rowsPerImage * dataLayout.bytesPerRow;
                }
            }
        }
    } else {
        uint32_t width = copySize.width;
        uint32_t height = copySize.height;
        GLenum adjustedFormat = format.format;
        if (format.format == GL_STENCIL) {
            DAWN_ASSERT(gl.GetVersion().IsDesktop() ||
                        gl.IsGLExtensionSupported("GL_OES_texture_stencil8"));
            adjustedFormat = GL_STENCIL_INDEX;
        }
        if (dataLayout.bytesPerRow % blockInfo.byteSize == 0) {
            // Valid values for GL_UNPACK_ALIGNMENT are 1, 2, 4, 8
            gl.PixelStorei(GL_UNPACK_ALIGNMENT, std::min(8u, blockInfo.byteSize));
            gl.PixelStorei(GL_UNPACK_ROW_LENGTH,
                           dataLayout.bytesPerRow / blockInfo.byteSize * blockInfo.width);
            if (target == GL_TEXTURE_2D) {
                gl.TexSubImage2D(target, destination.mipLevel, x, y, width, height, adjustedFormat,
                                 format.type, data);
            } else if (target == GL_TEXTURE_CUBE_MAP) {
                DAWN_ASSERT(texture->GetArrayLayers() == 6);
                const uint8_t* pointer = static_cast<const uint8_t*>(data);
                uint32_t baseLayer = destination.origin.z;
                for (uint32_t l = 0; l < copySize.depthOrArrayLayers; ++l) {
                    GLenum cubeMapTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + baseLayer + l;
                    gl.TexSubImage2D(cubeMapTarget, destination.mipLevel, x, y, width, height,
                                     adjustedFormat, format.type, pointer);
                    pointer += dataLayout.rowsPerImage * dataLayout.bytesPerRow;
                }
            } else {
                DAWN_ASSERT(target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY ||
                            target == GL_TEXTURE_CUBE_MAP_ARRAY);
                gl.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, dataLayout.rowsPerImage * blockInfo.height);
                gl.TexSubImage3D(target, destination.mipLevel, x, y, z, width, height,
                                 copySize.depthOrArrayLayers, adjustedFormat, format.type, data);
                gl.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
            }
            gl.PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
            gl.PixelStorei(GL_UNPACK_ALIGNMENT, 4);  // Reset to default
        } else {
            if (target == GL_TEXTURE_2D) {
                const uint8_t* d = static_cast<const uint8_t*>(data);
                for (; y < destination.origin.y + height; ++y) {
                    gl.TexSubImage2D(target, destination.mipLevel, x, y, width, 1, adjustedFormat,
                                     format.type, d);
                    d += dataLayout.bytesPerRow;
                }
            } else if (target == GL_TEXTURE_CUBE_MAP) {
                DAWN_ASSERT(texture->GetArrayLayers() == 6);
                const uint8_t* pointer = static_cast<const uint8_t*>(data);
                uint32_t baseLayer = destination.origin.z;
                for (uint32_t l = 0; l < copySize.depthOrArrayLayers; ++l) {
                    const uint8_t* d = pointer;
                    GLenum cubeMapTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + baseLayer + l;
                    for (y = destination.origin.y; y < destination.origin.y + height; ++y) {
                        gl.TexSubImage2D(cubeMapTarget, destination.mipLevel, x, y, width, 1,
                                         adjustedFormat, format.type, d);
                        d += dataLayout.bytesPerRow;
                    }
                    pointer += dataLayout.rowsPerImage * dataLayout.bytesPerRow;
                }
            } else {
                DAWN_ASSERT(target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY ||
                            target == GL_TEXTURE_CUBE_MAP_ARRAY);
                const uint8_t* slice = static_cast<const uint8_t*>(data);
                for (; z < destination.origin.z + copySize.depthOrArrayLayers; ++z) {
                    const uint8_t* d = slice;
                    for (y = destination.origin.y; y < destination.origin.y + height; ++y) {
                        gl.TexSubImage3D(target, destination.mipLevel, x, y, z, width, 1, 1,
                                         adjustedFormat, format.type, d);
                        d += dataLayout.bytesPerRow;
                    }
                    slice += dataLayout.rowsPerImage * dataLayout.bytesPerRow;
                }
            }
        }
    }
}

}  // namespace dawn::native::opengl
