// Copyright 2017 The NXT 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 "backend/opengl/CommandBufferGL.h"

#include "backend/Commands.h"
#include "backend/opengl/BufferGL.h"
#include "backend/opengl/ComputePipelineGL.h"
#include "backend/opengl/InputStateGL.h"
#include "backend/opengl/OpenGLBackend.h"
#include "backend/opengl/PersistentPipelineStateGL.h"
#include "backend/opengl/PipelineLayoutGL.h"
#include "backend/opengl/RenderPipelineGL.h"
#include "backend/opengl/SamplerGL.h"
#include "backend/opengl/TextureGL.h"

#include <cstring>

namespace backend { namespace opengl {

    namespace {

        GLenum IndexFormatType(nxt::IndexFormat format) {
            switch (format) {
                case nxt::IndexFormat::Uint16:
                    return GL_UNSIGNED_SHORT;
                case nxt::IndexFormat::Uint32:
                    return GL_UNSIGNED_INT;
                default:
                    UNREACHABLE();
            }
        }

        GLenum VertexFormatType(nxt::VertexFormat format) {
            switch (format) {
                case nxt::VertexFormat::FloatR32G32B32A32:
                case nxt::VertexFormat::FloatR32G32B32:
                case nxt::VertexFormat::FloatR32G32:
                case nxt::VertexFormat::FloatR32:
                    return GL_FLOAT;
                case nxt::VertexFormat::IntR32G32B32A32:
                case nxt::VertexFormat::IntR32G32B32:
                case nxt::VertexFormat::IntR32G32:
                case nxt::VertexFormat::IntR32:
                    return GL_INT;
                case nxt::VertexFormat::UshortR16G16B16A16:
                case nxt::VertexFormat::UshortR16G16:
                    return GL_UNSIGNED_SHORT;
                case nxt::VertexFormat::UnormR8G8B8A8:
                case nxt::VertexFormat::UnormR8G8:
                    return GL_UNSIGNED_BYTE;
                default:
                    UNREACHABLE();
            }
        }

        GLboolean VertexFormatIsNormalized(nxt::VertexFormat format) {
            switch (format) {
                case nxt::VertexFormat::UnormR8G8B8A8:
                case nxt::VertexFormat::UnormR8G8:
                    return GL_TRUE;
                default:
                    return GL_FALSE;
            }
        }

        // Push constants are implemented using OpenGL uniforms, however they aren't part of the
        // global OpenGL state but are part of the program state instead. This means that we have to
        // reapply push constants on pipeline change.
        //
        // This structure tracks the current values of push constants as well as dirty bits for push
        // constants that should be applied before the next draw or dispatch.
        class PushConstantTracker {
          public:
            void OnBeginPass() {
                for (auto stage : IterateStages(kAllStages)) {
                    mValues[stage].fill(0);
                    // No need to set dirty bits as a pipeline will be set before the next operation
                    // using push constants.
                }
            }

            void OnSetPushConstants(nxt::ShaderStageBit stages,
                                    uint32_t count,
                                    uint32_t offset,
                                    const uint32_t* data) {
                for (auto stage : IterateStages(stages)) {
                    memcpy(&mValues[stage][offset], data, count * sizeof(uint32_t));

                    // Use 64 bit masks and make sure there are no shift UB
                    static_assert(kMaxPushConstants <= 8 * sizeof(unsigned long long) - 1, "");
                    mDirtyBits[stage] |= ((1ull << count) - 1ull) << offset;
                }
            }

            void OnSetPipeline(PipelineBase* pipeline) {
                for (auto stage : IterateStages(kAllStages)) {
                    mDirtyBits[stage] = pipeline->GetPushConstants(stage).mask;
                }
            }

            void Apply(PipelineBase* pipeline, PipelineGL* glPipeline) {
                for (auto stage : IterateStages(kAllStages)) {
                    const auto& pushConstants = pipeline->GetPushConstants(stage);
                    const auto& glPushConstants = glPipeline->GetGLPushConstants(stage);

                    for (uint32_t constant :
                         IterateBitSet(mDirtyBits[stage] & pushConstants.mask)) {
                        GLint location = glPushConstants[constant];
                        switch (pushConstants.types[constant]) {
                            case PushConstantType::Int:
                                glUniform1i(location,
                                            *reinterpret_cast<GLint*>(&mValues[stage][constant]));
                                break;
                            case PushConstantType::UInt:
                                glUniform1ui(location,
                                             *reinterpret_cast<GLuint*>(&mValues[stage][constant]));
                                break;
                            case PushConstantType::Float:
                                float value;
                                // Use a memcpy to avoid strict-aliasing warnings, even if it is
                                // still technically undefined behavior.
                                memcpy(&value, &mValues[stage][constant], sizeof(value));
                                glUniform1f(location, value);
                                break;
                        }
                    }

                    mDirtyBits[stage].reset();
                }
            }

          private:
            PerStage<std::array<uint32_t, kMaxPushConstants>> mValues;
            PerStage<std::bitset<kMaxPushConstants>> mDirtyBits;
        };

        // Vertex buffers and index buffers are implemented as part of an OpenGL VAO that
        // corresponds to an InputState. On the contrary in NXT they are part of the global state.
        // This means that we have to re-apply these buffers on an InputState change.
        class InputBufferTracker {
          public:
            void OnBeginPass() {
                // We don't know what happened between this pass and the last one, just reset the
                // input state so everything gets reapplied.
                mLastInputState = nullptr;
            }

            void OnSetIndexBuffer(BufferBase* buffer) {
                mIndexBufferDirty = true;
                mIndexBuffer = ToBackend(buffer);
            }

            void OnSetVertexBuffers(uint32_t startSlot,
                                    uint32_t count,
                                    Ref<BufferBase>* buffers,
                                    uint32_t* offsets) {
                for (uint32_t i = 0; i < count; ++i) {
                    uint32_t slot = startSlot + i;
                    mVertexBuffers[slot] = ToBackend(buffers[i].Get());
                    mVertexBufferOffsets[slot] = offsets[i];
                }

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

            void OnSetPipeline(RenderPipelineBase* pipeline) {
                InputStateBase* inputState = pipeline->GetInputState();
                if (mLastInputState == inputState) {
                    return;
                }

                mIndexBufferDirty = true;
                mDirtyVertexBuffers |= inputState->GetInputsSetMask();

                mLastInputState = ToBackend(inputState);
            }

            void Apply() {
                if (mIndexBufferDirty && mIndexBuffer != nullptr) {
                    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->GetHandle());
                    mIndexBufferDirty = false;
                }

                for (uint32_t slot :
                     IterateBitSet(mDirtyVertexBuffers & mLastInputState->GetInputsSetMask())) {
                    for (uint32_t location :
                         IterateBitSet(mLastInputState->GetAttributesUsingInput(slot))) {
                        auto attribute = mLastInputState->GetAttribute(location);

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

                        auto input = mLastInputState->GetInput(slot);
                        auto components = VertexFormatNumComponents(attribute.format);
                        auto formatType = VertexFormatType(attribute.format);

                        GLboolean normalized = VertexFormatIsNormalized(attribute.format);
                        glBindBuffer(GL_ARRAY_BUFFER, buffer);
                        glVertexAttribPointer(
                            location, components, formatType, normalized, input.stride,
                            reinterpret_cast<void*>(
                                static_cast<intptr_t>(offset + attribute.offset)));
                    }
                }

                mDirtyVertexBuffers.reset();
            }

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

            std::bitset<kMaxVertexInputs> mDirtyVertexBuffers;
            std::array<Buffer*, kMaxVertexInputs> mVertexBuffers;
            std::array<uint32_t, kMaxVertexInputs> mVertexBufferOffsets;

            InputState* mLastInputState = nullptr;
        };

    }  // namespace

    CommandBuffer::CommandBuffer(CommandBufferBuilder* builder)
        : CommandBufferBase(builder), mCommands(builder->AcquireCommands()) {
    }

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

    void CommandBuffer::Execute() {
        Command type;
        PipelineBase* lastPipeline = nullptr;
        PipelineGL* lastGLPipeline = nullptr;
        RenderPipeline* lastRenderPipeline = nullptr;
        uint32_t indexBufferBaseOffset = 0;

        PersistentPipelineState persistentPipelineState;
        persistentPipelineState.SetDefaultState();

        PushConstantTracker pushConstants;
        InputBufferTracker inputBuffers;

        GLuint currentFBO = 0;

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

                case Command::BeginRenderPass: {
                    auto* cmd = mCommands.NextCommand<BeginRenderPassCmd>();
                    RenderPassDescriptor* info = ToBackend(cmd->info.Get());

                    pushConstants.OnBeginPass();
                    inputBuffers.OnBeginPass();

                    // 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.
                    glBindFramebuffer(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.
                    glGenFramebuffers(1, &currentFBO);
                    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, currentFBO);

                    // 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(info->GetColorAttachmentMask())) {
                        TextureViewBase* textureView = info->GetColorAttachment(i).view.Get();
                        GLuint texture = ToBackend(textureView->GetTexture())->GetHandle();

                        // Attach color buffers.
                        glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
                                               GL_TEXTURE_2D, texture, 0);
                        drawBuffers[i] = GL_COLOR_ATTACHMENT0 + i;
                        attachmentCount = i + 1;

                        // TODO(kainino@chromium.org): the color clears (later in
                        // this function) may be undefined for non-normalized integer formats.
                        nxt::TextureFormat format = textureView->GetTexture()->GetFormat();
                        ASSERT(format == nxt::TextureFormat::R8G8B8A8Unorm ||
                               format == nxt::TextureFormat::R8G8Unorm ||
                               format == nxt::TextureFormat::R8Unorm ||
                               format == nxt::TextureFormat::B8G8R8A8Unorm);
                    }
                    glDrawBuffers(attachmentCount, drawBuffers.data());

                    if (info->HasDepthStencilAttachment()) {
                        TextureViewBase* textureView = info->GetDepthStencilAttachment().view.Get();
                        GLuint texture = ToBackend(textureView->GetTexture())->GetHandle();
                        nxt::TextureFormat 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.
                        if (TextureFormatHasDepth(format)) {
                            if (TextureFormatHasStencil(format)) {
                                glAttachment = GL_DEPTH_STENCIL_ATTACHMENT;
                            } else {
                                glAttachment = GL_DEPTH_ATTACHMENT;
                            }
                        } else {
                            glAttachment = GL_STENCIL_ATTACHMENT;
                        }

                        glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, glAttachment, GL_TEXTURE_2D,
                                               texture, 0);

                        // TODO(kainino@chromium.org): the depth/stencil clears (later in
                        // this function) may be undefined for other texture formats.
                        ASSERT(format == nxt::TextureFormat::D32FloatS8Uint);
                    }

                    // Clear framebuffer attachments as needed

                    for (uint32_t i : IterateBitSet(info->GetColorAttachmentMask())) {
                        const auto& attachmentInfo = info->GetColorAttachment(i);

                        // Load op - color
                        if (attachmentInfo.loadOp == nxt::LoadOp::Clear) {
                            glClearBufferfv(GL_COLOR, i, attachmentInfo.clearColor.data());
                        }
                    }

                    if (info->HasDepthStencilAttachment()) {
                        const auto& attachmentInfo = info->GetDepthStencilAttachment();
                        nxt::TextureFormat attachmentFormat =
                            attachmentInfo.view->GetTexture()->GetFormat();

                        // Load op - depth/stencil
                        bool doDepthClear = TextureFormatHasDepth(attachmentFormat) &&
                                            (attachmentInfo.depthLoadOp == nxt::LoadOp::Clear);
                        bool doStencilClear = TextureFormatHasStencil(attachmentFormat) &&
                                              (attachmentInfo.stencilLoadOp == nxt::LoadOp::Clear);
                        if (doDepthClear && doStencilClear) {
                            glClearBufferfi(GL_DEPTH_STENCIL, 0, attachmentInfo.clearDepth,
                                            attachmentInfo.clearStencil);
                        } else if (doDepthClear) {
                            glClearBufferfv(GL_DEPTH, 0, &attachmentInfo.clearDepth);
                        } else if (doStencilClear) {
                            const GLint clearStencil = attachmentInfo.clearStencil;
                            glClearBufferiv(GL_STENCIL, 0, &clearStencil);
                        }
                    }

                    glBlendColor(0, 0, 0, 0);
                    glViewport(0, 0, info->GetWidth(), info->GetHeight());
                    glScissor(0, 0, info->GetWidth(), info->GetHeight());
                } break;

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

                    glBindBuffer(GL_PIXEL_PACK_BUFFER, ToBackend(src.buffer)->GetHandle());
                    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, ToBackend(dst.buffer)->GetHandle());
                    glCopyBufferSubData(GL_PIXEL_PACK_BUFFER, GL_PIXEL_UNPACK_BUFFER, src.offset,
                                        dst.offset, copy->size);

                    glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
                    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
                } break;

                case Command::CopyBufferToTexture: {
                    CopyBufferToTextureCmd* copy = mCommands.NextCommand<CopyBufferToTextureCmd>();
                    auto& src = copy->source;
                    auto& dst = copy->destination;
                    Buffer* buffer = ToBackend(src.buffer.Get());
                    Texture* texture = ToBackend(dst.texture.Get());
                    GLenum target = texture->GetGLTarget();
                    auto format = texture->GetGLFormat();

                    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer->GetHandle());
                    glActiveTexture(GL_TEXTURE0);
                    glBindTexture(target, texture->GetHandle());

                    ASSERT(texture->GetDimension() == nxt::TextureDimension::e2D);
                    glPixelStorei(GL_UNPACK_ROW_LENGTH,
                                  copy->rowPitch / TextureFormatPixelSize(texture->GetFormat()));
                    glTexSubImage2D(target, dst.level, dst.x, dst.y, dst.width, dst.height,
                                    format.format, format.type,
                                    reinterpret_cast<void*>(static_cast<uintptr_t>(src.offset)));
                    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
                    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
                } break;

                case Command::CopyTextureToBuffer: {
                    CopyTextureToBufferCmd* copy = mCommands.NextCommand<CopyTextureToBufferCmd>();
                    auto& src = copy->source;
                    auto& dst = copy->destination;
                    Texture* texture = ToBackend(src.texture.Get());
                    Buffer* buffer = ToBackend(dst.buffer.Get());
                    auto format = texture->GetGLFormat();

                    // 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.
                    ASSERT(texture->GetDimension() == nxt::TextureDimension::e2D);
                    glBindTexture(GL_TEXTURE_2D, texture->GetHandle());

                    GLuint readFBO = 0;
                    glGenFramebuffers(1, &readFBO);
                    glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);

                    glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
                                           texture->GetHandle(), src.level);

                    glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer->GetHandle());
                    glPixelStorei(GL_PACK_ROW_LENGTH,
                                  copy->rowPitch / TextureFormatPixelSize(texture->GetFormat()));
                    ASSERT(src.depth == 1 && src.z == 0);
                    void* offset = reinterpret_cast<void*>(static_cast<uintptr_t>(dst.offset));
                    glReadPixels(src.x, src.y, src.width, src.height, format.format, format.type,
                                 offset);
                    glPixelStorei(GL_PACK_ROW_LENGTH, 0);

                    glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
                    glDeleteFramebuffers(1, &readFBO);
                } break;

                case Command::Dispatch: {
                    DispatchCmd* dispatch = mCommands.NextCommand<DispatchCmd>();
                    pushConstants.Apply(lastPipeline, lastGLPipeline);
                    glDispatchCompute(dispatch->x, dispatch->y, dispatch->z);
                    // TODO(cwallez@chromium.org): add barriers to the API
                    glMemoryBarrier(GL_ALL_BARRIER_BITS);
                } break;

                case Command::DrawArrays: {
                    DrawArraysCmd* draw = mCommands.NextCommand<DrawArraysCmd>();
                    pushConstants.Apply(lastPipeline, lastGLPipeline);
                    inputBuffers.Apply();

                    if (draw->firstInstance > 0) {
                        glDrawArraysInstancedBaseInstance(
                            lastRenderPipeline->GetGLPrimitiveTopology(), draw->firstVertex,
                            draw->vertexCount, draw->instanceCount, draw->firstInstance);
                    } else {
                        // This branch is only needed on OpenGL < 4.2
                        glDrawArraysInstanced(lastRenderPipeline->GetGLPrimitiveTopology(),
                                              draw->firstVertex, draw->vertexCount,
                                              draw->instanceCount);
                    }
                } break;

                case Command::DrawElements: {
                    DrawElementsCmd* draw = mCommands.NextCommand<DrawElementsCmd>();
                    pushConstants.Apply(lastPipeline, lastGLPipeline);
                    inputBuffers.Apply();

                    nxt::IndexFormat indexFormat = lastRenderPipeline->GetIndexFormat();
                    size_t formatSize = IndexFormatSize(indexFormat);
                    GLenum formatType = IndexFormatType(indexFormat);

                    if (draw->firstInstance > 0) {
                        glDrawElementsInstancedBaseInstance(
                            lastRenderPipeline->GetGLPrimitiveTopology(), draw->indexCount,
                            formatType,
                            reinterpret_cast<void*>(draw->firstIndex * formatSize +
                                                    indexBufferBaseOffset),
                            draw->instanceCount, draw->firstInstance);
                    } else {
                        // This branch is only needed on OpenGL < 4.2
                        glDrawElementsInstanced(
                            lastRenderPipeline->GetGLPrimitiveTopology(), draw->indexCount,
                            formatType,
                            reinterpret_cast<void*>(draw->firstIndex * formatSize +
                                                    indexBufferBaseOffset),
                            draw->instanceCount);
                    }
                } break;

                case Command::EndComputePass: {
                    mCommands.NextCommand<EndComputePassCmd>();
                } break;

                case Command::EndRenderPass: {
                    mCommands.NextCommand<EndRenderPassCmd>();
                    glDeleteFramebuffers(1, &currentFBO);
                    currentFBO = 0;
                } break;

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

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

                    pushConstants.OnSetPipeline(lastPipeline);
                    inputBuffers.OnSetPipeline(lastRenderPipeline);
                } break;

                case Command::SetPushConstants: {
                    SetPushConstantsCmd* cmd = mCommands.NextCommand<SetPushConstantsCmd>();
                    uint32_t* data = mCommands.NextData<uint32_t>(cmd->count);
                    pushConstants.OnSetPushConstants(cmd->stages, cmd->count, cmd->offset, data);
                } break;

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

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

                case Command::SetBlendColor: {
                    SetBlendColorCmd* cmd = mCommands.NextCommand<SetBlendColorCmd>();
                    glBlendColor(cmd->r, cmd->g, cmd->b, cmd->a);
                } break;

                case Command::SetBindGroup: {
                    SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>();
                    size_t groupIndex = cmd->index;
                    BindGroup* group = ToBackend(cmd->group.Get());

                    const auto& indices =
                        ToBackend(lastPipeline->GetLayout())->GetBindingIndexInfo()[groupIndex];
                    const auto& layout = group->GetLayout()->GetBindingInfo();

                    for (uint32_t binding : IterateBitSet(layout.mask)) {
                        switch (layout.types[binding]) {
                            case nxt::BindingType::UniformBuffer: {
                                BufferView* view =
                                    ToBackend(group->GetBindingAsBufferView(binding));
                                GLuint buffer = ToBackend(view->GetBuffer())->GetHandle();
                                GLuint uboIndex = indices[binding];

                                glBindBufferRange(GL_UNIFORM_BUFFER, uboIndex, buffer,
                                                  view->GetOffset(), view->GetSize());
                            } break;

                            case nxt::BindingType::Sampler: {
                                GLuint sampler =
                                    ToBackend(group->GetBindingAsSampler(binding))->GetHandle();
                                GLuint samplerIndex = indices[binding];

                                for (auto unit :
                                     lastGLPipeline->GetTextureUnitsForSampler(samplerIndex)) {
                                    glBindSampler(unit, sampler);
                                }
                            } break;

                            case nxt::BindingType::SampledTexture: {
                                TextureView* view =
                                    ToBackend(group->GetBindingAsTextureView(binding));
                                Texture* texture = ToBackend(view->GetTexture());
                                GLuint handle = texture->GetHandle();
                                GLenum target = texture->GetGLTarget();
                                GLuint textureIndex = indices[binding];

                                for (auto unit :
                                     lastGLPipeline->GetTextureUnitsForTexture(textureIndex)) {
                                    glActiveTexture(GL_TEXTURE0 + unit);
                                    glBindTexture(target, handle);
                                }
                            } break;

                            case nxt::BindingType::StorageBuffer: {
                                BufferView* view =
                                    ToBackend(group->GetBindingAsBufferView(binding));
                                GLuint buffer = ToBackend(view->GetBuffer())->GetHandle();
                                GLuint ssboIndex = indices[binding];

                                glBindBufferRange(GL_SHADER_STORAGE_BUFFER, ssboIndex, buffer,
                                                  view->GetOffset(), view->GetSize());
                            } break;
                        }
                    }
                } break;

                case Command::SetIndexBuffer: {
                    SetIndexBufferCmd* cmd = mCommands.NextCommand<SetIndexBufferCmd>();
                    indexBufferBaseOffset = cmd->offset;
                    inputBuffers.OnSetIndexBuffer(cmd->buffer.Get());
                } break;

                case Command::SetVertexBuffers: {
                    SetVertexBuffersCmd* cmd = mCommands.NextCommand<SetVertexBuffersCmd>();
                    auto buffers = mCommands.NextData<Ref<BufferBase>>(cmd->count);
                    auto offsets = mCommands.NextData<uint32_t>(cmd->count);
                    inputBuffers.OnSetVertexBuffers(cmd->startSlot, cmd->count, buffers, offsets);
                } break;

                case Command::TransitionBufferUsage: {
                    TransitionBufferUsageCmd* cmd =
                        mCommands.NextCommand<TransitionBufferUsageCmd>();

                    cmd->buffer->UpdateUsageInternal(cmd->usage);
                } break;

                case Command::TransitionTextureUsage: {
                    TransitionTextureUsageCmd* cmd =
                        mCommands.NextCommand<TransitionTextureUsageCmd>();

                    cmd->texture->UpdateUsageInternal(cmd->usage);
                } break;
            }
        }

        // HACK: cleanup a tiny bit of state to make this work with
        // virtualized contexts enabled in Chromium
        glBindSampler(0, 0);
    }

}}  // namespace backend::opengl
