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

#include "dawn_native/BindGroup.h"
#include "dawn_native/BindGroupTracker.h"
#include "dawn_native/CommandEncoder.h"
#include "dawn_native/Commands.h"
#include "dawn_native/RenderBundle.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/RenderPipelineGL.h"
#include "dawn_native/opengl/SamplerGL.h"
#include "dawn_native/opengl/TextureGL.h"
#include "dawn_native/opengl/UtilsGL.h"

#include <cstring>

namespace dawn_native { namespace 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;
                default:
                    UNREACHABLE();
            }
        }

        GLenum VertexFormatType(wgpu::VertexFormat format) {
            switch (format) {
                case wgpu::VertexFormat::UChar2:
                case wgpu::VertexFormat::UChar4:
                case wgpu::VertexFormat::UChar2Norm:
                case wgpu::VertexFormat::UChar4Norm:
                    return GL_UNSIGNED_BYTE;
                case wgpu::VertexFormat::Char2:
                case wgpu::VertexFormat::Char4:
                case wgpu::VertexFormat::Char2Norm:
                case wgpu::VertexFormat::Char4Norm:
                    return GL_BYTE;
                case wgpu::VertexFormat::UShort2:
                case wgpu::VertexFormat::UShort4:
                case wgpu::VertexFormat::UShort2Norm:
                case wgpu::VertexFormat::UShort4Norm:
                    return GL_UNSIGNED_SHORT;
                case wgpu::VertexFormat::Short2:
                case wgpu::VertexFormat::Short4:
                case wgpu::VertexFormat::Short2Norm:
                case wgpu::VertexFormat::Short4Norm:
                    return GL_SHORT;
                case wgpu::VertexFormat::Half2:
                case wgpu::VertexFormat::Half4:
                    return GL_HALF_FLOAT;
                case wgpu::VertexFormat::Float:
                case wgpu::VertexFormat::Float2:
                case wgpu::VertexFormat::Float3:
                case wgpu::VertexFormat::Float4:
                    return GL_FLOAT;
                case wgpu::VertexFormat::UInt:
                case wgpu::VertexFormat::UInt2:
                case wgpu::VertexFormat::UInt3:
                case wgpu::VertexFormat::UInt4:
                    return GL_UNSIGNED_INT;
                case wgpu::VertexFormat::Int:
                case wgpu::VertexFormat::Int2:
                case wgpu::VertexFormat::Int3:
                case wgpu::VertexFormat::Int4:
                    return GL_INT;
                default:
                    UNREACHABLE();
            }
        }

        GLboolean VertexFormatIsNormalized(wgpu::VertexFormat format) {
            switch (format) {
                case wgpu::VertexFormat::UChar2Norm:
                case wgpu::VertexFormat::UChar4Norm:
                case wgpu::VertexFormat::Char2Norm:
                case wgpu::VertexFormat::Char4Norm:
                case wgpu::VertexFormat::UShort2Norm:
                case wgpu::VertexFormat::UShort4Norm:
                case wgpu::VertexFormat::Short2Norm:
                case wgpu::VertexFormat::Short4Norm:
                    return GL_TRUE;
                default:
                    return GL_FALSE;
            }
        }

        bool VertexFormatIsInt(wgpu::VertexFormat format) {
            switch (format) {
                case wgpu::VertexFormat::UChar2:
                case wgpu::VertexFormat::UChar4:
                case wgpu::VertexFormat::Char2:
                case wgpu::VertexFormat::Char4:
                case wgpu::VertexFormat::UShort2:
                case wgpu::VertexFormat::UShort4:
                case wgpu::VertexFormat::Short2:
                case wgpu::VertexFormat::Short4:
                case wgpu::VertexFormat::UInt:
                case wgpu::VertexFormat::UInt2:
                case wgpu::VertexFormat::UInt3:
                case wgpu::VertexFormat::UInt4:
                case wgpu::VertexFormat::Int:
                case wgpu::VertexFormat::Int2:
                case wgpu::VertexFormat::Int3:
                case wgpu::VertexFormat::Int4:
                    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(uint32_t slot, BufferBase* buffer, uint64_t offset) {
                mVertexBuffers[slot] = ToBackend(buffer);
                mVertexBufferOffsets[slot] = offset;

                // Use 64 bit masks and make sure there are no shift UB
                static_assert(kMaxVertexBuffers <= 8 * sizeof(unsigned long long) - 1, "");
                mDirtyVertexBuffers |= 1ull << slot;
            }

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

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

                mLastPipeline = pipeline;
            }

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

                for (uint32_t slot : IterateBitSet(mDirtyVertexBuffers &
                                                   mLastPipeline->GetVertexBufferSlotsUsed())) {
                    for (uint32_t location :
                         IterateBitSet(mLastPipeline->GetAttributesUsingVertexBuffer(slot))) {
                        const VertexAttributeInfo& attribute =
                            mLastPipeline->GetAttribute(location);

                        GLuint buffer = mVertexBuffers[slot]->GetHandle();
                        uint64_t offset = mVertexBufferOffsets[slot];

                        const VertexBufferInfo& vertexBuffer = mLastPipeline->GetVertexBuffer(slot);
                        uint32_t components = VertexFormatNumComponents(attribute.format);
                        GLenum formatType = VertexFormatType(attribute.format);

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

                mDirtyVertexBuffers.reset();
            }

          private:
            bool mIndexBufferDirty = false;
            Buffer* mIndexBuffer = nullptr;

            std::bitset<kMaxVertexBuffers> mDirtyVertexBuffers;
            std::array<Buffer*, kMaxVertexBuffers> mVertexBuffers;
            std::array<uint64_t, kMaxVertexBuffers> mVertexBufferOffsets;

            RenderPipelineBase* mLastPipeline = nullptr;
        };

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

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

            void Apply(const OpenGLFunctions& gl) {
                for (uint32_t index : IterateBitSet(mDirtyBindGroupsObjectChangedOrIsDynamic)) {
                    ApplyBindGroup(gl, index, mBindGroups[index], mDynamicOffsetCounts[index],
                                   mDynamicOffsets[index].data());
                }
                DidApply();
            }

          private:
            void ApplyBindGroup(const OpenGLFunctions& gl,
                                uint32_t index,
                                BindGroupBase* group,
                                uint32_t dynamicOffsetCount,
                                uint64_t* dynamicOffsets) {
                const auto& indices = ToBackend(mPipelineLayout)->GetBindingIndexInfo()[index];
                const BindGroupLayoutBase::LayoutBindingInfo& layout =
                    group->GetLayout()->GetBindingInfo();
                uint32_t currentDynamicIndex = 0;

                for (BindingIndex bindingIndex = 0; bindingIndex < layout.bindingCount;
                     ++bindingIndex) {
                    switch (layout.types[bindingIndex]) {
                        case wgpu::BindingType::UniformBuffer: {
                            BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex);
                            GLuint buffer = ToBackend(binding.buffer)->GetHandle();
                            GLuint uboIndex = indices[bindingIndex];
                            GLuint offset = binding.offset;

                            if (layout.hasDynamicOffset[bindingIndex]) {
                                offset += dynamicOffsets[currentDynamicIndex];
                                ++currentDynamicIndex;
                            }

                            gl.BindBufferRange(GL_UNIFORM_BUFFER, uboIndex, buffer, offset,
                                               binding.size);
                        } break;

                        case wgpu::BindingType::Sampler: {
                            Sampler* sampler = ToBackend(group->GetBindingAsSampler(bindingIndex));
                            GLuint samplerIndex = indices[bindingIndex];

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

                        case wgpu::BindingType::SampledTexture: {
                            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);
                            }
                        } break;

                        case wgpu::BindingType::StorageBuffer:
                        case wgpu::BindingType::ReadonlyStorageBuffer: {
                            BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex);
                            GLuint buffer = ToBackend(binding.buffer)->GetHandle();
                            GLuint ssboIndex = indices[bindingIndex];
                            GLuint offset = binding.offset;

                            if (layout.hasDynamicOffset[bindingIndex]) {
                                offset += dynamicOffsets[currentDynamicIndex];
                                ++currentDynamicIndex;
                            }

                            gl.BindBufferRange(GL_SHADER_STORAGE_BUFFER, ssboIndex, buffer, offset,
                                               binding.size);
                        } break;

                        case wgpu::BindingType::StorageTexture:
                        case wgpu::BindingType::ReadonlyStorageTexture:
                        case wgpu::BindingType::WriteonlyStorageTexture:
                            UNREACHABLE();
                            break;

                            // TODO(shaobo.yan@intel.com): Implement dynamic buffer offset.
                    }
                }
            }

            PipelineGL* mPipeline = nullptr;
        };

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

            GLuint readFbo = 0;
            GLuint writeFbo = 0;

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

                    const TextureBase* colorTexture =
                        renderPass->colorAttachments[i].view->GetTexture();
                    ASSERT(colorTexture->IsMultisampledTexture());
                    ASSERT(colorTexture->GetArrayLayers() == 1);
                    ASSERT(renderPass->colorAttachments[i].view->GetBaseMipLevel() == 0);

                    GLuint colorHandle = ToBackend(colorTexture)->GetHandle();
                    gl.BindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
                    gl.FramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                                            ToBackend(colorTexture)->GetGLTarget(), colorHandle, 0);

                    const TextureBase* resolveTexture =
                        renderPass->colorAttachments[i].resolveTarget->GetTexture();
                    GLuint resolveTextureHandle = ToBackend(resolveTexture)->GetHandle();
                    GLuint resolveTargetMipmapLevel =
                        renderPass->colorAttachments[i].resolveTarget->GetBaseMipLevel();
                    gl.BindFramebuffer(GL_DRAW_FRAMEBUFFER, writeFbo);
                    if (resolveTexture->GetArrayLayers() == 1) {
                        gl.FramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                                                GL_TEXTURE_2D, resolveTextureHandle,
                                                resolveTargetMipmapLevel);
                    } else {
                        GLuint resolveTargetArrayLayer =
                            renderPass->colorAttachments[i].resolveTarget->GetBaseArrayLayer();
                        gl.FramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                                                   resolveTextureHandle, resolveTargetMipmapLevel,
                                                   resolveTargetArrayLayer);
                    }

                    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->GetMipLevelVirtualSize(textureCopy.mipLevel);
            if (textureCopy.origin.x + copySize.width > virtualSizeAtLevel.width) {
                ASSERT(texture->GetFormat().isCompressed);
                validTextureCopyExtent.width = virtualSizeAtLevel.width - textureCopy.origin.x;
            }
            if (textureCopy.origin.y + copySize.height > virtualSizeAtLevel.height) {
                ASSERT(texture->GetFormat().isCompressed);
                validTextureCopyExtent.height = virtualSizeAtLevel.height - textureCopy.origin.y;
            }

            return validTextureCopyExtent;
        }

    }  // namespace

    CommandBuffer::CommandBuffer(CommandEncoder* encoder, const CommandBufferDescriptor* descriptor)
        : CommandBufferBase(encoder, descriptor), mCommands(encoder->AcquireCommands()) {
    }

    CommandBuffer::~CommandBuffer() {
        FreeCommands(&mCommands);
    }

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

        auto TransitionForPass = [](const PassResourceUsage& usages) {
            for (size_t i = 0; i < usages.textures.size(); i++) {
                Texture* texture = ToBackend(usages.textures[i]);
                // Clear textures that are not output attachments. Output attachments will be
                // cleared in BeginRenderPass by setting the loadop to clear when the
                // texture subresource has not been initialized before the render pass.
                if (!(usages.textureUsages[i] & wgpu::TextureUsage::OutputAttachment)) {
                    texture->EnsureSubresourceContentInitialized(0, texture->GetNumMipLevels(), 0,
                                                                 texture->GetArrayLayers());
                }
            }
        };

        const std::vector<PassResourceUsage>& passResourceUsages = GetResourceUsages().perPass;
        uint32_t nextPassNumber = 0;

        Command type;
        while (mCommands.NextCommandId(&type)) {
            switch (type) {
                case Command::BeginComputePass: {
                    mCommands.NextCommand<BeginComputePassCmd>();
                    TransitionForPass(passResourceUsages[nextPassNumber]);
                    ExecuteComputePass();

                    nextPassNumber++;
                } break;

                case Command::BeginRenderPass: {
                    auto* cmd = mCommands.NextCommand<BeginRenderPassCmd>();
                    TransitionForPass(passResourceUsages[nextPassNumber]);

                    LazyClearRenderPassAttachments(cmd);
                    ExecuteRenderPass(cmd);

                    nextPassNumber++;
                } break;

                case Command::CopyBufferToBuffer: {
                    CopyBufferToBufferCmd* copy = mCommands.NextCommand<CopyBufferToBufferCmd>();

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

                case Command::CopyBufferToTexture: {
                    CopyBufferToTextureCmd* copy = mCommands.NextCommand<CopyBufferToTextureCmd>();
                    auto& src = copy->source;
                    auto& dst = copy->destination;
                    auto& copySize = copy->copySize;
                    Buffer* buffer = ToBackend(src.buffer.Get());
                    Texture* texture = ToBackend(dst.texture.Get());
                    GLenum target = texture->GetGLTarget();
                    const GLFormat& format = texture->GetGLFormat();
                    if (IsCompleteSubresourceCopiedTo(texture, copySize, dst.mipLevel)) {
                        texture->SetIsSubresourceContentInitialized(true, dst.mipLevel, 1,
                                                                    dst.arrayLayer, 1);
                    } else {
                        texture->EnsureSubresourceContentInitialized(dst.mipLevel, 1,
                                                                     dst.arrayLayer, 1);
                    }

                    gl.BindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer->GetHandle());
                    gl.ActiveTexture(GL_TEXTURE0);
                    gl.BindTexture(target, texture->GetHandle());

                    const Format& formatInfo = texture->GetFormat();
                    gl.PixelStorei(GL_UNPACK_ROW_LENGTH,
                                   src.rowPitch / formatInfo.blockByteSize * formatInfo.blockWidth);
                    gl.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, src.imageHeight);

                    if (formatInfo.isCompressed) {
                        gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_SIZE, formatInfo.blockByteSize);
                        gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_WIDTH, formatInfo.blockWidth);
                        gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_HEIGHT, formatInfo.blockHeight);
                        gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_DEPTH, 1);

                        ASSERT(texture->GetDimension() == wgpu::TextureDimension::e2D);
                        uint64_t copyDataSize = (copySize.width / formatInfo.blockWidth) *
                                                (copySize.height / formatInfo.blockHeight) *
                                                formatInfo.blockByteSize;
                        Extent3D copyExtent = ComputeTextureCopyExtent(dst, copySize);

                        if (texture->GetArrayLayers() > 1) {
                            gl.CompressedTexSubImage3D(
                                target, dst.mipLevel, dst.origin.x, dst.origin.y, dst.arrayLayer,
                                copyExtent.width, copyExtent.height, 1, format.internalFormat,
                                copyDataSize,
                                reinterpret_cast<void*>(static_cast<uintptr_t>(src.offset)));
                        } else {
                            gl.CompressedTexSubImage2D(
                                target, dst.mipLevel, dst.origin.x, dst.origin.y, copyExtent.width,
                                copyExtent.height, format.internalFormat, copyDataSize,
                                reinterpret_cast<void*>(static_cast<uintptr_t>(src.offset)));
                        }
                    } else {
                        switch (texture->GetDimension()) {
                            case wgpu::TextureDimension::e2D:
                                if (texture->GetArrayLayers() > 1) {
                                    gl.TexSubImage3D(target, dst.mipLevel, dst.origin.x,
                                                     dst.origin.y, dst.arrayLayer, copySize.width,
                                                     copySize.height, 1, format.format, format.type,
                                                     reinterpret_cast<void*>(
                                                         static_cast<uintptr_t>(src.offset)));
                                } else {
                                    gl.TexSubImage2D(target, dst.mipLevel, dst.origin.x,
                                                     dst.origin.y, copySize.width, copySize.height,
                                                     format.format, format.type,
                                                     reinterpret_cast<void*>(
                                                         static_cast<uintptr_t>(src.offset)));
                                }
                                break;

                            default:
                                UNREACHABLE();
                        }
                    }

                    gl.PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
                    gl.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);

                    gl.BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
                } break;

                case Command::CopyTextureToBuffer: {
                    CopyTextureToBufferCmd* copy = mCommands.NextCommand<CopyTextureToBufferCmd>();
                    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 GLFormat& format = texture->GetGLFormat();
                    GLenum target = texture->GetGLTarget();

                    // TODO(jiawei.shao@intel.com): support texture-to-buffer copy with compressed
                    // texture formats.
                    if (texture->GetFormat().isCompressed) {
                        UNREACHABLE();
                    }

                    texture->EnsureSubresourceContentInitialized(src.mipLevel, 1, src.arrayLayer,
                                                                 1);
                    // 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);
                    switch (texture->GetDimension()) {
                        case wgpu::TextureDimension::e2D:
                            if (texture->GetArrayLayers() > 1) {
                                gl.FramebufferTextureLayer(
                                    GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture->GetHandle(),
                                    src.mipLevel, src.arrayLayer);
                            } else {
                                gl.FramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                                                        GL_TEXTURE_2D, texture->GetHandle(),
                                                        src.mipLevel);
                            }
                            break;

                        default:
                            UNREACHABLE();
                    }

                    gl.BindBuffer(GL_PIXEL_PACK_BUFFER, buffer->GetHandle());
                    gl.PixelStorei(GL_PACK_ROW_LENGTH,
                                   dst.rowPitch / texture->GetFormat().blockByteSize);
                    gl.PixelStorei(GL_PACK_IMAGE_HEIGHT, dst.imageHeight);
                    ASSERT(copySize.depth == 1 && src.origin.z == 0);
                    void* offset = reinterpret_cast<void*>(static_cast<uintptr_t>(dst.offset));
                    gl.ReadPixels(src.origin.x, src.origin.y, copySize.width, copySize.height,
                                  format.format, format.type, offset);
                    gl.PixelStorei(GL_PACK_ROW_LENGTH, 0);
                    gl.PixelStorei(GL_PACK_IMAGE_HEIGHT, 0);

                    gl.BindBuffer(GL_PIXEL_PACK_BUFFER, 0);
                    gl.DeleteFramebuffers(1, &readFBO);
                } break;

                case Command::CopyTextureToTexture: {
                    CopyTextureToTextureCmd* copy =
                        mCommands.NextCommand<CopyTextureToTextureCmd>();
                    auto& src = copy->source;
                    auto& dst = copy->destination;

                    // TODO(jiawei.shao@intel.com): 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());
                    srcTexture->EnsureSubresourceContentInitialized(src.mipLevel, 1, src.arrayLayer,
                                                                    1);
                    if (IsCompleteSubresourceCopiedTo(dstTexture, copySize, dst.mipLevel)) {
                        dstTexture->SetIsSubresourceContentInitialized(true, dst.mipLevel, 1,
                                                                       dst.arrayLayer, 1);
                    } else {
                        dstTexture->EnsureSubresourceContentInitialized(dst.mipLevel, 1,
                                                                        dst.arrayLayer, 1);
                    }
                    gl.CopyImageSubData(srcTexture->GetHandle(), srcTexture->GetGLTarget(),
                                        src.mipLevel, src.origin.x, src.origin.y, src.arrayLayer,
                                        dstTexture->GetHandle(), dstTexture->GetGLTarget(),
                                        dst.mipLevel, dst.origin.x, dst.origin.y, dst.arrayLayer,
                                        copySize.width, copySize.height, 1);
                } break;

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

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

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

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

                    gl.DispatchCompute(dispatch->x, dispatch->y, dispatch->z);
                    // TODO(cwallez@chromium.org): add barriers to the API
                    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));
                    // TODO(cwallez@chromium.org): add barriers to the API
                    gl.MemoryBarrier(GL_ALL_BARRIER_BITS);
                } 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;

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

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

    void CommandBuffer::ExecuteRenderPass(BeginRenderPassCmd* renderPass) {
        const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
        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).
            std::array<GLenum, kMaxColorAttachments> drawBuffers = {};

            // Construct GL framebuffer

            unsigned int attachmentCount = 0;
            for (uint32_t i :
                 IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
                TextureViewBase* textureView = renderPass->colorAttachments[i].view.Get();
                GLuint texture = ToBackend(textureView->GetTexture())->GetHandle();

                // Attach color buffers.
                if (textureView->GetTexture()->GetArrayLayers() == 1) {
                    GLenum target = ToBackend(textureView->GetTexture())->GetGLTarget();
                    gl.FramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, target,
                                            texture, textureView->GetBaseMipLevel());
                } else {
                    gl.FramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
                                               texture, textureView->GetBaseMipLevel(),
                                               textureView->GetBaseArrayLayer());
                }
                drawBuffers[i] = GL_COLOR_ATTACHMENT0 + i;
                attachmentCount = i + 1;
            }
            gl.DrawBuffers(attachmentCount, drawBuffers.data());

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

                // Attach depth/stencil buffer.
                GLenum glAttachment = 0;
                // TODO(kainino@chromium.org): it may be valid to just always use
                // GL_DEPTH_STENCIL_ATTACHMENT here.
                switch (format.aspect) {
                    case Format::Aspect::Depth:
                        glAttachment = GL_DEPTH_ATTACHMENT;
                        break;
                    case Format::Aspect::Stencil:
                        glAttachment = GL_STENCIL_ATTACHMENT;
                        break;
                    case Format::Aspect::DepthStencil:
                        glAttachment = GL_DEPTH_STENCIL_ATTACHMENT;
                        break;
                    default:
                        UNREACHABLE();
                        break;
                }

                GLenum target = ToBackend(textureView->GetTexture())->GetGLTarget();
                gl.FramebufferTexture2D(GL_DRAW_FRAMEBUFFER, glAttachment, target, texture, 0);
            }
        }

        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);
        gl.DepthRangef(0.0, 1.0);
        gl.Scissor(0, 0, renderPass->width, renderPass->height);

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

                // Load op - color
                // TODO(cwallez@chromium.org): Choose the clear function depending on the
                // componentType: things work for now because the clear color is always a float, but
                // when that's fixed will lose precision on integer formats when converting to
                // float.
                if (attachmentInfo->loadOp == wgpu::LoadOp::Clear) {
                    gl.ColorMaski(i, true, true, true, true);
                    gl.ClearBufferfv(GL_COLOR, i, &attachmentInfo->clearColor.r);
                }

                if (attachmentInfo->storeOp == wgpu::StoreOp::Clear) {
                    // 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;

        VertexStateBufferBindingTracker vertexStateBufferBindingTracker;
        BindGroupTracker bindGroupTracker = {};

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

                    if (draw->firstInstance > 0) {
                        gl.DrawArraysInstancedBaseInstance(
                            lastPipeline->GetGLPrimitiveTopology(), draw->firstVertex,
                            draw->vertexCount, draw->instanceCount, draw->firstInstance);
                    } else {
                        // This branch is only needed on OpenGL < 4.2
                        gl.DrawArraysInstanced(lastPipeline->GetGLPrimitiveTopology(),
                                               draw->firstVertex, draw->vertexCount,
                                               draw->instanceCount);
                    }
                } break;

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

                    wgpu::IndexFormat indexFormat =
                        lastPipeline->GetVertexStateDescriptor()->indexFormat;
                    size_t formatSize = IndexFormatSize(indexFormat);
                    GLenum formatType = IndexFormatType(indexFormat);

                    if (draw->firstInstance > 0) {
                        gl.DrawElementsInstancedBaseVertexBaseInstance(
                            lastPipeline->GetGLPrimitiveTopology(), draw->indexCount, formatType,
                            reinterpret_cast<void*>(draw->firstIndex * formatSize +
                                                    indexBufferBaseOffset),
                            draw->instanceCount, draw->baseVertex, draw->firstInstance);
                    } else {
                        // This branch is only needed on OpenGL < 4.2; ES < 3.2
                        if (draw->baseVertex != 0) {
                            gl.DrawElementsInstancedBaseVertex(
                                lastPipeline->GetGLPrimitiveTopology(), draw->indexCount,
                                formatType,
                                reinterpret_cast<void*>(draw->firstIndex * formatSize +
                                                        indexBufferBaseOffset),
                                draw->instanceCount, draw->baseVertex);
                        } else {
                            // This branch is only needed on OpenGL < 3.2; ES < 3.2
                            gl.DrawElementsInstanced(
                                lastPipeline->GetGLPrimitiveTopology(), draw->indexCount,
                                formatType,
                                reinterpret_cast<void*>(draw->firstIndex * formatSize +
                                                        indexBufferBaseOffset),
                                draw->instanceCount);
                        }
                    }
                } break;

                case Command::DrawIndirect: {
                    DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>();
                    vertexStateBufferBindingTracker.Apply(gl);
                    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)));
                } break;

                case Command::DrawIndexedIndirect: {
                    DrawIndexedIndirectCmd* draw = iter->NextCommand<DrawIndexedIndirectCmd>();
                    vertexStateBufferBindingTracker.Apply(gl);
                    bindGroupTracker.Apply(gl);

                    wgpu::IndexFormat indexFormat =
                        lastPipeline->GetVertexStateDescriptor()->indexFormat;
                    GLenum formatType = IndexFormatType(indexFormat);

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

                    gl.BindBuffer(GL_DRAW_INDIRECT_BUFFER, indirectBuffer->GetHandle());
                    gl.DrawElementsIndirect(
                        lastPipeline->GetGLPrimitiveTopology(), formatType,
                        reinterpret_cast<void*>(static_cast<intptr_t>(indirectBufferOffset)));
                } 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);
                } 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;
                    vertexStateBufferBindingTracker.OnSetIndexBuffer(cmd->buffer.Get());
                } break;

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

                default:
                    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;
                } break;

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

                case Command::SetViewport: {
                    SetViewportCmd* cmd = mCommands.NextCommand<SetViewportCmd>();
                    gl.ViewportIndexedf(0, cmd->x, cmd->y, cmd->width, cmd->height);
                    gl.DepthRangef(cmd->minDepth, cmd->maxDepth);
                } break;

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

                case Command::SetBlendColor: {
                    SetBlendColorCmd* cmd = mCommands.NextCommand<SetBlendColorCmd>();
                    gl.BlendColor(cmd->color.r, cmd->color.g, cmd->color.b, 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)) {
                            DoRenderBundleCommand(iter, type);
                        }
                    }
                } break;

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

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

}}  // namespace dawn_native::opengl
