//
// Copyright 2024 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// ContextWgpu.cpp:
//    Implements the class methods for ContextWgpu.
//

#include "libANGLE/renderer/wgpu/ContextWgpu.h"
#include "common/unsafe_buffers.h"

#include "common/PackedEnums.h"
#include "common/debug.h"

#include "compiler/translator/wgsl/OutputUniformBlocks.h"
#include "libANGLE/Context.h"
#include "libANGLE/Error.h"
#include "libANGLE/renderer/wgpu/BufferWgpu.h"
#include "libANGLE/renderer/wgpu/CompilerWgpu.h"
#include "libANGLE/renderer/wgpu/DisplayWgpu.h"
#include "libANGLE/renderer/wgpu/FenceNVWgpu.h"
#include "libANGLE/renderer/wgpu/FramebufferWgpu.h"
#include "libANGLE/renderer/wgpu/ImageWgpu.h"
#include "libANGLE/renderer/wgpu/ProgramExecutableWgpu.h"
#include "libANGLE/renderer/wgpu/ProgramPipelineWgpu.h"
#include "libANGLE/renderer/wgpu/ProgramWgpu.h"
#include "libANGLE/renderer/wgpu/QueryWgpu.h"
#include "libANGLE/renderer/wgpu/RenderbufferWgpu.h"
#include "libANGLE/renderer/wgpu/SamplerWgpu.h"
#include "libANGLE/renderer/wgpu/ShaderWgpu.h"
#include "libANGLE/renderer/wgpu/SyncWgpu.h"
#include "libANGLE/renderer/wgpu/TextureWgpu.h"
#include "libANGLE/renderer/wgpu/TransformFeedbackWgpu.h"
#include "libANGLE/renderer/wgpu/VertexArrayWgpu.h"
#include "libANGLE/renderer/wgpu/wgpu_pipeline_state.h"
#include "libANGLE/renderer/wgpu/wgpu_utils.h"

namespace rx
{

namespace
{

constexpr angle::PackedEnumMap<webgpu::RenderPassClosureReason, const char *>
    kRenderPassClosureReason = {{
        {webgpu::RenderPassClosureReason::NewRenderPass,
         "Render pass closed due to starting a new render pass"},
        {webgpu::RenderPassClosureReason::FramebufferBindingChange,
         "Render pass closed due to framebuffer binding change"},
        {webgpu::RenderPassClosureReason::FramebufferInternalChange,
         "Render pass closed due to framebuffer internal change"},
        {webgpu::RenderPassClosureReason::GLFlush, "Render pass closed due to glFlush"},
        {webgpu::RenderPassClosureReason::GLFinish, "Render pass closed due to glFinish"},
        {webgpu::RenderPassClosureReason::EGLSwapBuffers,
         "Render pass closed due to eglSwapBuffers"},
        {webgpu::RenderPassClosureReason::GLReadPixels, "Render pass closed due to glReadPixels"},
        {webgpu::RenderPassClosureReason::IndexRangeReadback,
         "Render pass closed due to index buffer read back for streamed client data"},
        {webgpu::RenderPassClosureReason::VertexArrayStreaming,
         "Render pass closed for uploading streamed client data"},
        {webgpu::RenderPassClosureReason::VertexArrayLineLoop,
         "Render pass closed for line loop emulation"},
        {webgpu::RenderPassClosureReason::CopyBufferToTexture,
         "Render pass closed to update texture"},
        {webgpu::RenderPassClosureReason::CopyTextureToTexture,
         "Render pass closed to copy texture"},
        {webgpu::RenderPassClosureReason::CopyImage, "Render pass closed to copy image"},
        {webgpu::RenderPassClosureReason::ClearWithDraw,
         "Render pass closed to clear with a draw call (e.g. for scissored or masked clears)"},
    }};

}  // namespace

ContextWgpu::ContextWgpu(const gl::State &state, gl::ErrorSet *errorSet, DisplayWgpu *display)
    : ContextImpl(state, errorSet), mDisplay(display)
{
    mNewRenderPassDirtyBits = DirtyBits{
        DIRTY_BIT_RENDER_PIPELINE_BINDING,  // The pipeline needs to be bound for each renderpass
        DIRTY_BIT_VIEWPORT,
        DIRTY_BIT_SCISSOR,
        DIRTY_BIT_STENCIL_REF,
        DIRTY_BIT_BLEND_CONSTANT,
        DIRTY_BIT_VERTEX_BUFFERS,
        DIRTY_BIT_INDEX_BUFFER,
        DIRTY_BIT_DRIVER_UNIFORMS,
        DIRTY_BIT_BIND_GROUPS,
    };
}

ContextWgpu::~ContextWgpu() {}

void ContextWgpu::onDestroy(const gl::Context *context)
{
    mImageLoadContext = {};
}

angle::Result ContextWgpu::initialize(const angle::ImageLoadContext &imageLoadContext)
{
    const DawnProcTable *wgpu = webgpu::GetProcs(this);

    mImageLoadContext = imageLoadContext;

    // Create the driver uniform bind group layout, which won't ever change.
    WGPUBindGroupLayoutEntry driverUniformBindGroupEntry = WGPU_BIND_GROUP_LAYOUT_ENTRY_INIT;
    driverUniformBindGroupEntry.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment;
    driverUniformBindGroupEntry.binding               = sh::kDriverUniformBlockBinding;
    driverUniformBindGroupEntry.buffer.type           = WGPUBufferBindingType_Uniform;
    driverUniformBindGroupEntry.buffer.minBindingSize = kDriverUniformSize;
    driverUniformBindGroupEntry.texture.sampleType    = WGPUTextureSampleType_BindingNotUsed;
    driverUniformBindGroupEntry.sampler.type          = WGPUSamplerBindingType_BindingNotUsed;
    driverUniformBindGroupEntry.storageTexture.access = WGPUStorageTextureAccess_BindingNotUsed;
    // Create a bind group layout with these entries.
    WGPUBindGroupLayoutDescriptor driverUniformsBindGroupLayoutDesc =
        WGPU_BIND_GROUP_LAYOUT_DESCRIPTOR_INIT;
    driverUniformsBindGroupLayoutDesc.entryCount = 1;
    driverUniformsBindGroupLayoutDesc.entries    = &driverUniformBindGroupEntry;
    mDriverUniformsBindGroupLayout               = webgpu::BindGroupLayoutHandle::Acquire(
        wgpu,
        wgpu->deviceCreateBindGroupLayout(getDevice().get(), &driverUniformsBindGroupLayoutDesc));

    // Driver uniforms should be set to 0 for later memcmp.
    ANGLE_UNSAFE_TODO(memset(&mDriverUniforms, 0, sizeof(mDriverUniforms)));

    return angle::Result::Continue;
}

angle::Result ContextWgpu::onFramebufferChange(FramebufferWgpu *framebufferWgpu,
                                               gl::Command command)
{
    // May modify framebuffer size, so invalidate driver uniforms which contain the framebuffer
    // size.
    invalidateDriverUniforms();

    // If internal framebuffer state changes, always end the render pass
    ANGLE_TRY(endRenderPass(webgpu::RenderPassClosureReason::FramebufferInternalChange));

    return angle::Result::Continue;
}

angle::Result ContextWgpu::flush(const gl::Context *context)
{
    return flush(webgpu::RenderPassClosureReason::GLFlush);
}

angle::Result ContextWgpu::flush(webgpu::RenderPassClosureReason closureReason)
{
    ANGLE_TRY(endRenderPass(closureReason));

    if (mCurrentCommandEncoder)
    {
        const DawnProcTable *wgpu                 = webgpu::GetProcs(this);
        webgpu::CommandBufferHandle commandBuffer = webgpu::CommandBufferHandle::Acquire(
            wgpu, wgpu->commandEncoderFinish(mCurrentCommandEncoder.get(), nullptr));
        mCurrentCommandEncoder            = nullptr;

        wgpu->queueSubmit(getQueue().get(), 1, &commandBuffer.get());
    }

    return angle::Result::Continue;
}

void ContextWgpu::setColorAttachmentFormat(size_t colorIndex, WGPUTextureFormat format)
{
    if (mRenderPipelineDesc.setColorAttachmentFormat(colorIndex, format))
    {
        invalidateCurrentRenderPipeline();
    }
}

void ContextWgpu::setColorAttachmentFormats(const gl::DrawBuffersArray<WGPUTextureFormat> &formats)
{
    for (size_t i = 0; i < formats.size(); i++)
    {
        setColorAttachmentFormat(i, formats[i]);
    }
}

void ContextWgpu::setDepthStencilFormat(WGPUTextureFormat format)
{
    if (mRenderPipelineDesc.setDepthStencilAttachmentFormat(format))
    {
        invalidateCurrentRenderPipeline();
    }
}

void ContextWgpu::setVertexAttribute(size_t attribIndex, webgpu::PackedVertexAttribute newAttrib)
{
    if (mRenderPipelineDesc.setVertexAttribute(attribIndex, newAttrib))
    {
        invalidateCurrentRenderPipeline();
    }
}

void ContextWgpu::invalidateVertexBuffer(size_t slot)
{
    if (mCurrentRenderPipelineAllAttributes[slot])
    {
        mDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS);
        mDirtyVertexBuffers.set(slot);
    }
}

void ContextWgpu::invalidateVertexBuffers()
{
    mDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS);
    mDirtyVertexBuffers = mCurrentRenderPipelineAllAttributes;
}

void ContextWgpu::invalidateIndexBuffer()
{
    mDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
}

void ContextWgpu::invalidateCurrentTextures()
{
    ProgramExecutableWgpu *executableWgpu = webgpu::GetImpl(mState.getProgramExecutable());
    executableWgpu->markSamplerBindingsDirty();
    mDirtyBits.set(DIRTY_BIT_BIND_GROUPS);
}

void ContextWgpu::invalidateDriverUniforms()
{
    mDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS);
}

void ContextWgpu::ensureCommandEncoderCreated()
{
    if (!mCurrentCommandEncoder)
    {
        const DawnProcTable *wgpu = webgpu::GetProcs(this);
        mCurrentCommandEncoder    = webgpu::CommandEncoderHandle::Acquire(
            wgpu, wgpu->deviceCreateCommandEncoder(getDevice().get(), nullptr));
    }
}

angle::Result ContextWgpu::getCurrentCommandEncoder(webgpu::RenderPassClosureReason closureReason,
                                                    webgpu::CommandEncoderHandle *outHandle)
{
    if (hasActiveRenderPass())
    {
        ANGLE_TRY(endRenderPass(closureReason));
    }
    ensureCommandEncoderCreated();
    *outHandle = mCurrentCommandEncoder;
    return angle::Result::Continue;
}

angle::Result ContextWgpu::finish(const gl::Context *context)
{
    const DawnProcTable *wgpu = webgpu::GetProcs(this);

    ANGLE_TRY(flush(webgpu::RenderPassClosureReason::GLFinish));

    WGPUQueueWorkDoneCallbackInfo callback = WGPU_QUEUE_WORK_DONE_CALLBACK_INFO_INIT;
    callback.mode                          = WGPUCallbackMode_WaitAnyOnly;
    callback.callback                      = [](WGPUQueueWorkDoneStatus status,
                           WGPUStringView message,
                           void *userdata1, void *userdata2) {
        ASSERT(userdata1 == nullptr);
        ASSERT(userdata2 == nullptr);
    };

    WGPUFutureWaitInfo onWorkSubmittedFuture = WGPU_FUTURE_WAIT_INFO_INIT;
    onWorkSubmittedFuture.future = wgpu->queueOnSubmittedWorkDone(getQueue().get(), callback);

    WGPUWaitStatus status =
        wgpu->instanceWaitAny(getInstance().get(), 1, &onWorkSubmittedFuture, -1);
    ASSERT(!webgpu::IsWgpuError(status));

    return angle::Result::Continue;
}

angle::Result ContextWgpu::drawArrays(const gl::Context *context,
                                      gl::PrimitiveMode mode,
                                      GLint first,
                                      GLsizei count)
{
    if (mode == gl::PrimitiveMode::TriangleFan)
    {
        UNIMPLEMENTED();
        return angle::Result::Continue;
    }

    uint32_t firstIndex = 0;
    uint32_t indexCount = static_cast<uint32_t>(count);
    ANGLE_TRY(setupDraw(context, mode, first, count, 1, gl::DrawElementsType::InvalidEnum, nullptr,
                        0, &firstIndex, &indexCount));
    if (mode == gl::PrimitiveMode::LineLoop)
    {
        mCommandBuffer.drawIndexed(indexCount, 1, firstIndex, 0, 0);
    }
    else
    {
        mCommandBuffer.draw(static_cast<uint32_t>(count), 1, static_cast<uint32_t>(first), 0);
    }
    return angle::Result::Continue;
}

angle::Result ContextWgpu::drawArraysInstanced(const gl::Context *context,
                                               gl::PrimitiveMode mode,
                                               GLint first,
                                               GLsizei count,
                                               GLsizei instanceCount)
{
    if (mode == gl::PrimitiveMode::TriangleFan)
    {
        UNIMPLEMENTED();
        return angle::Result::Continue;
    }

    uint32_t firstIndex = 0;
    uint32_t indexCount = static_cast<uint32_t>(count);
    ANGLE_TRY(setupDraw(context, mode, first, count, instanceCount,
                        gl::DrawElementsType::InvalidEnum, nullptr, 0, &firstIndex, &indexCount));
    if (mode == gl::PrimitiveMode::LineLoop)
    {
        mCommandBuffer.drawIndexed(indexCount, static_cast<uint32_t>(instanceCount), firstIndex, 0,
                                   0);
    }
    else
    {
        mCommandBuffer.draw(indexCount, static_cast<uint32_t>(instanceCount),
                            static_cast<uint32_t>(first), 0);
    }
    return angle::Result::Continue;
}

angle::Result ContextWgpu::drawArraysInstancedBaseInstance(const gl::Context *context,
                                                           gl::PrimitiveMode mode,
                                                           GLint first,
                                                           GLsizei count,
                                                           GLsizei instanceCount,
                                                           GLuint baseInstance)
{
    if (mode == gl::PrimitiveMode::TriangleFan)
    {
        UNIMPLEMENTED();
        return angle::Result::Continue;
    }

    uint32_t firstIndex = 0;
    uint32_t indexCount = static_cast<uint32_t>(count);
    ANGLE_TRY(setupDraw(context, mode, first, count, instanceCount,
                        gl::DrawElementsType::InvalidEnum, nullptr, 0, &firstIndex, &indexCount));
    if (mode == gl::PrimitiveMode::LineLoop)
    {
        mCommandBuffer.drawIndexed(indexCount, static_cast<uint32_t>(instanceCount), firstIndex, 0,
                                   baseInstance);
    }
    else
    {
        mCommandBuffer.draw(static_cast<uint32_t>(count), static_cast<uint32_t>(instanceCount),
                            static_cast<uint32_t>(first), baseInstance);
    }
    return angle::Result::Continue;
}

angle::Result ContextWgpu::drawElements(const gl::Context *context,
                                        gl::PrimitiveMode mode,
                                        GLsizei count,
                                        gl::DrawElementsType type,
                                        const void *indices)
{
    uint32_t firstVertex = 0;
    uint32_t indexCount  = static_cast<uint32_t>(count);
    if (mode == gl::PrimitiveMode::TriangleFan)
    {
        UNIMPLEMENTED();
        return angle::Result::Continue;
    }

    ANGLE_TRY(setupDraw(context, mode, 0, count, 1, type, indices, 0, &firstVertex, &indexCount));
    mCommandBuffer.drawIndexed(indexCount, 1, firstVertex, 0, 0);
    return angle::Result::Continue;
}

angle::Result ContextWgpu::drawElementsBaseVertex(const gl::Context *context,
                                                  gl::PrimitiveMode mode,
                                                  GLsizei count,
                                                  gl::DrawElementsType type,
                                                  const void *indices,
                                                  GLint baseVertex)
{
    uint32_t firstVertex = 0;
    uint32_t indexCount  = static_cast<uint32_t>(count);
    if (mode == gl::PrimitiveMode::TriangleFan)
    {
        UNIMPLEMENTED();
        return angle::Result::Continue;
    }

    ANGLE_TRY(setupDraw(context, mode, 0, count, 1, type, indices, baseVertex, &firstVertex,
                        &indexCount));
    mCommandBuffer.drawIndexed(indexCount, 1, firstVertex, static_cast<uint32_t>(baseVertex), 0);
    return angle::Result::Continue;
}

angle::Result ContextWgpu::drawElementsInstanced(const gl::Context *context,
                                                 gl::PrimitiveMode mode,
                                                 GLsizei count,
                                                 gl::DrawElementsType type,
                                                 const void *indices,
                                                 GLsizei instances)
{
    uint32_t firstVertex = 0;
    uint32_t indexCount  = static_cast<uint32_t>(count);
    if (mode == gl::PrimitiveMode::TriangleFan)
    {
        UNIMPLEMENTED();
        return angle::Result::Continue;
    }

    ANGLE_TRY(
        setupDraw(context, mode, 0, count, instances, type, indices, 0, &firstVertex, &indexCount));
    mCommandBuffer.drawIndexed(indexCount, static_cast<uint32_t>(instances), firstVertex, 0, 0);
    return angle::Result::Continue;
}

angle::Result ContextWgpu::drawElementsInstancedBaseVertex(const gl::Context *context,
                                                           gl::PrimitiveMode mode,
                                                           GLsizei count,
                                                           gl::DrawElementsType type,
                                                           const void *indices,
                                                           GLsizei instances,
                                                           GLint baseVertex)
{
    uint32_t firstVertex = 0;
    uint32_t indexCount  = static_cast<uint32_t>(count);
    if (mode == gl::PrimitiveMode::TriangleFan)
    {
        UNIMPLEMENTED();
        return angle::Result::Continue;
    }

    ANGLE_TRY(setupDraw(context, mode, 0, count, instances, type, indices, baseVertex, &firstVertex,
                        &indexCount));
    mCommandBuffer.drawIndexed(indexCount, static_cast<uint32_t>(instances), firstVertex,
                               static_cast<uint32_t>(baseVertex), 0);
    return angle::Result::Continue;
}

angle::Result ContextWgpu::drawElementsInstancedBaseVertexBaseInstance(const gl::Context *context,
                                                                       gl::PrimitiveMode mode,
                                                                       GLsizei count,
                                                                       gl::DrawElementsType type,
                                                                       const void *indices,
                                                                       GLsizei instances,
                                                                       GLint baseVertex,
                                                                       GLuint baseInstance)
{
    uint32_t firstVertex = 0;
    uint32_t indexCount  = static_cast<uint32_t>(count);
    if (mode == gl::PrimitiveMode::TriangleFan)
    {
        UNIMPLEMENTED();
        return angle::Result::Continue;
    }

    ANGLE_TRY(setupDraw(context, mode, 0, count, instances, type, indices, baseVertex, &firstVertex,
                        &indexCount));
    mCommandBuffer.drawIndexed(indexCount, static_cast<uint32_t>(instances), firstVertex,
                               static_cast<uint32_t>(baseVertex),
                               static_cast<uint32_t>(baseInstance));
    return angle::Result::Continue;
}

angle::Result ContextWgpu::drawRangeElements(const gl::Context *context,
                                             gl::PrimitiveMode mode,
                                             GLuint start,
                                             GLuint end,
                                             GLsizei count,
                                             gl::DrawElementsType type,
                                             const void *indices)
{
    return drawElements(context, mode, count, type, indices);
}

angle::Result ContextWgpu::drawRangeElementsBaseVertex(const gl::Context *context,
                                                       gl::PrimitiveMode mode,
                                                       GLuint start,
                                                       GLuint end,
                                                       GLsizei count,
                                                       gl::DrawElementsType type,
                                                       const void *indices,
                                                       GLint baseVertex)
{
    return drawElementsBaseVertex(context, mode, count, type, indices, baseVertex);
}

angle::Result ContextWgpu::drawArraysIndirect(const gl::Context *context,
                                              gl::PrimitiveMode mode,
                                              const void *indirect)
{
    UNIMPLEMENTED();
    return angle::Result::Continue;
}

angle::Result ContextWgpu::drawElementsIndirect(const gl::Context *context,
                                                gl::PrimitiveMode mode,
                                                gl::DrawElementsType type,
                                                const void *indirect)
{
    UNIMPLEMENTED();
    return angle::Result::Continue;
}

angle::Result ContextWgpu::multiDrawArrays(const gl::Context *context,
                                           gl::PrimitiveMode mode,
                                           const GLint *firsts,
                                           const GLsizei *counts,
                                           GLsizei drawcount)
{
    UNIMPLEMENTED();
    return angle::Result::Continue;
}

angle::Result ContextWgpu::multiDrawArraysInstanced(const gl::Context *context,
                                                    gl::PrimitiveMode mode,
                                                    const GLint *firsts,
                                                    const GLsizei *counts,
                                                    const GLsizei *instanceCounts,
                                                    GLsizei drawcount)
{
    UNIMPLEMENTED();
    return angle::Result::Continue;
}

angle::Result ContextWgpu::multiDrawArraysIndirect(const gl::Context *context,
                                                   gl::PrimitiveMode mode,
                                                   const void *indirect,
                                                   GLsizei drawcount,
                                                   GLsizei stride)
{
    UNIMPLEMENTED();
    return angle::Result::Continue;
}

angle::Result ContextWgpu::multiDrawElements(const gl::Context *context,
                                             gl::PrimitiveMode mode,
                                             const GLsizei *counts,
                                             gl::DrawElementsType type,
                                             const GLvoid *const *indices,
                                             GLsizei drawcount)
{
    UNIMPLEMENTED();
    return angle::Result::Continue;
}

angle::Result ContextWgpu::multiDrawElementsInstanced(const gl::Context *context,
                                                      gl::PrimitiveMode mode,
                                                      const GLsizei *counts,
                                                      gl::DrawElementsType type,
                                                      const GLvoid *const *indices,
                                                      const GLsizei *instanceCounts,
                                                      GLsizei drawcount)
{
    UNIMPLEMENTED();
    return angle::Result::Continue;
}

angle::Result ContextWgpu::multiDrawElementsIndirect(const gl::Context *context,
                                                     gl::PrimitiveMode mode,
                                                     gl::DrawElementsType type,
                                                     const void *indirect,
                                                     GLsizei drawcount,
                                                     GLsizei stride)
{
    UNIMPLEMENTED();
    return angle::Result::Continue;
}

angle::Result ContextWgpu::multiDrawArraysInstancedBaseInstance(const gl::Context *context,
                                                                gl::PrimitiveMode mode,
                                                                const GLint *firsts,
                                                                const GLsizei *counts,
                                                                const GLsizei *instanceCounts,
                                                                const GLuint *baseInstances,
                                                                GLsizei drawcount)
{
    UNIMPLEMENTED();
    return angle::Result::Continue;
}

angle::Result ContextWgpu::multiDrawElementsInstancedBaseVertexBaseInstance(
    const gl::Context *context,
    gl::PrimitiveMode mode,
    const GLsizei *counts,
    gl::DrawElementsType type,
    const GLvoid *const *indices,
    const GLsizei *instanceCounts,
    const GLint *baseVertices,
    const GLuint *baseInstances,
    GLsizei drawcount)
{
    UNIMPLEMENTED();
    return angle::Result::Continue;
}

gl::GraphicsResetStatus ContextWgpu::getResetStatus()
{
    return gl::GraphicsResetStatus::NoError;
}

angle::Result ContextWgpu::insertEventMarker(GLsizei length, const char *marker)
{
    return angle::Result::Continue;
}

angle::Result ContextWgpu::pushGroupMarker(GLsizei length, const char *marker)
{
    return angle::Result::Continue;
}

angle::Result ContextWgpu::popGroupMarker()
{
    return angle::Result::Continue;
}

angle::Result ContextWgpu::pushDebugGroup(const gl::Context *context,
                                          GLenum source,
                                          GLuint id,
                                          const std::string &message)
{
    return angle::Result::Continue;
}

angle::Result ContextWgpu::popDebugGroup(const gl::Context *context)
{
    return angle::Result::Continue;
}

angle::Result ContextWgpu::syncState(const gl::Context *context,
                                     const gl::state::DirtyBits dirtyBits,
                                     const gl::state::DirtyBits bitMask,
                                     const gl::state::ExtendedDirtyBits extendedDirtyBits,
                                     const gl::state::ExtendedDirtyBits extendedBitMask,
                                     gl::Command command)
{
    const gl::State &glState = context->getState();

    for (auto iter = dirtyBits.begin(), endIter = dirtyBits.end(); iter != endIter; ++iter)
    {
        size_t dirtyBit = *iter;
        switch (dirtyBit)
        {
            case gl::state::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
            {
                const FramebufferWgpu *framebufferWgpu =
                    webgpu::GetImpl(context->getState().getDrawFramebuffer());
                setColorAttachmentFormats(framebufferWgpu->getCurrentColorAttachmentFormats());
                setDepthStencilFormat(framebufferWgpu->getCurrentDepthStencilAttachmentFormat());

                // May modify framebuffer size, so invalidate driver uniforms which contain the
                // framebuffer size.
                invalidateDriverUniforms();
                updatePipelineColorMasks();
                ANGLE_TRY(endRenderPass(webgpu::RenderPassClosureReason::FramebufferBindingChange));
            }
            break;
            case gl::state::DIRTY_BIT_READ_FRAMEBUFFER_BINDING:
                break;
            case gl::state::DIRTY_BIT_SCISSOR_TEST_ENABLED:
                mDirtyBits.set(DIRTY_BIT_SCISSOR);
                break;
            case gl::state::DIRTY_BIT_SCISSOR:
                mDirtyBits.set(DIRTY_BIT_SCISSOR);
                break;
            case gl::state::DIRTY_BIT_VIEWPORT:
                mDirtyBits.set(DIRTY_BIT_VIEWPORT);
                break;
            case gl::state::DIRTY_BIT_DEPTH_RANGE:
                mDirtyBits.set(DIRTY_BIT_VIEWPORT);
                // Driver uniforms include the depth range, which has now changed.
                invalidateDriverUniforms();
                break;
            case gl::state::DIRTY_BIT_BLEND_ENABLED:
            {
                const gl::BlendStateExt &blendStateExt = mState.getBlendStateExt();
                gl::DrawBufferMask enabledMask         = blendStateExt.getEnabledMask();
                for (size_t i = 0; i < blendStateExt.getDrawBufferCount(); i++)
                {
                    if (mRenderPipelineDesc.setBlendEnabled(i, enabledMask.test(i)))
                    {
                        invalidateCurrentRenderPipeline();
                    }
                }
            }
                break;
            case gl::state::DIRTY_BIT_BLEND_COLOR:
                mDirtyBits.set(DIRTY_BIT_BLEND_CONSTANT);
                break;
            case gl::state::DIRTY_BIT_BLEND_FUNCS:
            {
                const gl::BlendStateExt &blendState = mState.getBlendStateExt();
                for (size_t i = 0; i < blendState.getDrawBufferCount(); i++)
                {
                    if (mRenderPipelineDesc.setBlendFuncs(
                            i, gl_wgpu::GetBlendFactor(blendState.getSrcColorIndexed(i)),
                            gl_wgpu::GetBlendFactor(blendState.getDstColorIndexed(i)),
                            gl_wgpu::GetBlendFactor(blendState.getSrcAlphaIndexed(i)),
                            gl_wgpu::GetBlendFactor(blendState.getDstAlphaIndexed(i))))
                    {
                        invalidateCurrentRenderPipeline();
                    }
                }
            }
                break;
            case gl::state::DIRTY_BIT_BLEND_EQUATIONS:
            {
                const gl::BlendStateExt &blendState = mState.getBlendStateExt();
                for (size_t i = 0; i < blendState.getDrawBufferCount(); i++)
                {
                    if (mRenderPipelineDesc.setBlendEquations(
                            i, gl_wgpu::GetBlendEquation(blendState.getEquationColorIndexed(i)),
                            gl_wgpu::GetBlendEquation(blendState.getEquationAlphaIndexed(i))))
                    {
                        invalidateCurrentRenderPipeline();
                    }
                }
            }
                break;
            case gl::state::DIRTY_BIT_COLOR_MASK:
            {
                updatePipelineColorMasks();
            }
            break;
            case gl::state::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
                // Driver uniforms include the sample alpha to coverage state.
                invalidateDriverUniforms();
                break;
            case gl::state::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED:
                break;
            case gl::state::DIRTY_BIT_SAMPLE_COVERAGE:
                break;
            case gl::state::DIRTY_BIT_SAMPLE_MASK_ENABLED:
                break;
            case gl::state::DIRTY_BIT_SAMPLE_MASK:
                break;
            case gl::state::DIRTY_BIT_DEPTH_TEST_ENABLED:
                // Enabled and func get combined into one state in WebGPU. Only sync it once.
                iter.setLaterBit(gl::state::DIRTY_BIT_DEPTH_FUNC);
                break;
            case gl::state::DIRTY_BIT_DEPTH_FUNC:
                if (mRenderPipelineDesc.setDepthFunc(
                        gl_wgpu::GetCompareFunc(glState.getDepthStencilState().depthFunc,
                                                glState.getDepthStencilState().depthTest)))
                {
                    invalidateCurrentRenderPipeline();
                }
                break;
            case gl::state::DIRTY_BIT_DEPTH_MASK:
                break;
            case gl::state::DIRTY_BIT_STENCIL_TEST_ENABLED:
                // Changing the state of stencil test affects both the front and back funcs, which
                // also dirties the stencil reference value (whcih won't be recorded in the render
                // pass while stencil testing is disabled).
                iter.setLaterBit(gl::state::DIRTY_BIT_STENCIL_FUNCS_FRONT);
                iter.setLaterBit(gl::state::DIRTY_BIT_STENCIL_FUNCS_BACK);
                // Disabling the stencil test is partially done by setting the writemask to 0, so it
                // must be marked as dirty as well.
                iter.setLaterBit(gl::state::DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
                break;
            case gl::state::DIRTY_BIT_STENCIL_FUNCS_FRONT:
                if (mRenderPipelineDesc.setStencilFrontFunc(
                        gl_wgpu::GetCompareFunc(glState.getDepthStencilState().stencilFunc,
                                                glState.getDepthStencilState().stencilTest)))
                {
                    invalidateCurrentRenderPipeline();
                }

                if (mRenderPipelineDesc.setStencilReadMask(
                        glState.getDepthStencilState().stencilTest
                            ? glState.getDepthStencilState().stencilMask
                            : 0))
                {
                    invalidateCurrentRenderPipeline();
                }

                mDirtyBits.set(DIRTY_BIT_STENCIL_REF);
                break;
            case gl::state::DIRTY_BIT_STENCIL_FUNCS_BACK:
                if (mRenderPipelineDesc.setStencilBackFunc(
                        gl_wgpu::GetCompareFunc(glState.getDepthStencilState().stencilBackFunc,
                                                glState.getDepthStencilState().stencilTest)))
                {
                    invalidateCurrentRenderPipeline();
                }

                // Stencil back read mask and ref value are ignored here. WebGL and WebGPU do not
                // support separate stencil read masks/write masks/ref values and so this backend
                // sets `noSeparateStencilRefsAndMasks`, which will cause a validation error on draw
                // if the stencil read masks/write masks/ref values differ between the front and the
                // back. See https://registry.khronos.org/webgl/specs/latest/1.0/#6.12 and
                // https://www.w3.org/TR/webgpu/#depth-stencil-state.
                break;
            case gl::state::DIRTY_BIT_STENCIL_OPS_FRONT:
            {
                WGPUStencilOperation failOp =
                    gl_wgpu::GetStencilOp(glState.getDepthStencilState().stencilFail);
                WGPUStencilOperation depthFailOp =
                    gl_wgpu::GetStencilOp(glState.getDepthStencilState().stencilPassDepthFail);
                WGPUStencilOperation passOp =
                    gl_wgpu::GetStencilOp(glState.getDepthStencilState().stencilPassDepthPass);
                if (mRenderPipelineDesc.setStencilFrontOps(failOp, depthFailOp, passOp))
                {
                    invalidateCurrentRenderPipeline();
                }
            }
            break;
            case gl::state::DIRTY_BIT_STENCIL_OPS_BACK:
            {
                WGPUStencilOperation failOp =
                    gl_wgpu::GetStencilOp(glState.getDepthStencilState().stencilBackFail);
                WGPUStencilOperation depthFailOp =
                    gl_wgpu::GetStencilOp(glState.getDepthStencilState().stencilBackPassDepthFail);
                WGPUStencilOperation passOp =
                    gl_wgpu::GetStencilOp(glState.getDepthStencilState().stencilBackPassDepthPass);
                if (mRenderPipelineDesc.setStencilBackOps(failOp, depthFailOp, passOp))
                {
                    invalidateCurrentRenderPipeline();
                }
            }
            break;
            case gl::state::DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
                if (mRenderPipelineDesc.setStencilWriteMask(
                        glState.getDepthStencilState().stencilTest
                            ? glState.getDepthStencilState().stencilWritemask
                            : 0))
                {
                    invalidateCurrentRenderPipeline();
                }
                break;
            case gl::state::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
                // Stencil back write mask is ignored here. WebGL and WebGPU do not support
                // separate stencil read masks/write masks/ref values and so this backend sets
                // `noSeparateStencilRefsAndMasks`, which will cause a validation error on draw if
                // the stencil read masks/write masks/ref values differ between the front and the
                // back. See https://registry.khronos.org/webgl/specs/latest/1.0/#6.12 and
                // https://www.w3.org/TR/webgpu/#depth-stencil-state.
                break;
            case gl::state::DIRTY_BIT_CULL_FACE_ENABLED:
            case gl::state::DIRTY_BIT_CULL_FACE:
                mRenderPipelineDesc.setCullMode(glState.getRasterizerState().cullMode,
                                                glState.getRasterizerState().cullFace);
                invalidateCurrentRenderPipeline();
                break;
            case gl::state::DIRTY_BIT_FRONT_FACE:
                mRenderPipelineDesc.setFrontFace(glState.getRasterizerState().frontFace);
                invalidateCurrentRenderPipeline();
                break;
            case gl::state::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
                break;
            case gl::state::DIRTY_BIT_POLYGON_OFFSET:
                break;
            case gl::state::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED:
                break;
            case gl::state::DIRTY_BIT_LINE_WIDTH:
                break;
            case gl::state::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED:
                break;
            case gl::state::DIRTY_BIT_CLEAR_COLOR:
                break;
            case gl::state::DIRTY_BIT_CLEAR_DEPTH:
                break;
            case gl::state::DIRTY_BIT_CLEAR_STENCIL:
                break;
            case gl::state::DIRTY_BIT_UNPACK_STATE:
                break;
            case gl::state::DIRTY_BIT_UNPACK_BUFFER_BINDING:
                break;
            case gl::state::DIRTY_BIT_PACK_STATE:
                break;
            case gl::state::DIRTY_BIT_PACK_BUFFER_BINDING:
                break;
            case gl::state::DIRTY_BIT_DITHER_ENABLED:
                break;
            case gl::state::DIRTY_BIT_RENDERBUFFER_BINDING:
                break;
            case gl::state::DIRTY_BIT_VERTEX_ARRAY_BINDING:
                invalidateCurrentRenderPipeline();
                break;
            case gl::state::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING:
                break;
            case gl::state::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING:
                break;
            case gl::state::DIRTY_BIT_PROGRAM_BINDING:
            case gl::state::DIRTY_BIT_PROGRAM_EXECUTABLE:
                invalidateCurrentRenderPipeline();
                iter.setLaterBit(gl::state::DIRTY_BIT_TEXTURE_BINDINGS);
                break;
            case gl::state::DIRTY_BIT_SAMPLER_BINDINGS:
                invalidateCurrentTextures();
                break;
            case gl::state::DIRTY_BIT_TEXTURE_BINDINGS:
                invalidateCurrentTextures();
                break;
            case gl::state::DIRTY_BIT_IMAGE_BINDINGS:
                invalidateCurrentTextures();
                break;
            case gl::state::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING:
                break;
            case gl::state::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS:
                break;
            case gl::state::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING:
                break;
            case gl::state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING:
                break;
            case gl::state::DIRTY_BIT_MULTISAMPLING:
                break;
            case gl::state::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE:
                break;
            case gl::state::DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE:
                break;
            case gl::state::DIRTY_BIT_CURRENT_VALUES:
                break;
            case gl::state::DIRTY_BIT_PROVOKING_VERTEX:
                break;
            case gl::state::DIRTY_BIT_SAMPLE_SHADING:
                break;
            case gl::state::DIRTY_BIT_PATCH_VERTICES:
                break;
            case gl::state::DIRTY_BIT_CLIP_CONTROL:
                // Driver uniforms are calculated using the clip control state.
                invalidateDriverUniforms();
                break;
            case gl::state::DIRTY_BIT_EXTENDED:
            {
                for (auto extendedIter    = extendedDirtyBits.begin(),
                          extendedEndIter = extendedDirtyBits.end();
                     extendedIter != extendedEndIter; ++extendedIter)
                {
                    const size_t extendedDirtyBit = *extendedIter;
                    switch (extendedDirtyBit)
                    {
                        case gl::state::EXTENDED_DIRTY_BIT_CLIP_DISTANCES:
                            // Driver uniforms include the clip distances.
                            invalidateDriverUniforms();
                            break;
                        case gl::state::EXTENDED_DIRTY_BIT_DEPTH_CLAMP_ENABLED:
                            break;
                        case gl::state::EXTENDED_DIRTY_BIT_MIPMAP_GENERATION_HINT:
                            break;
                        case gl::state::EXTENDED_DIRTY_BIT_POLYGON_MODE:
                            break;
                        case gl::state::EXTENDED_DIRTY_BIT_POLYGON_OFFSET_POINT_ENABLED:
                            break;
                        case gl::state::EXTENDED_DIRTY_BIT_POLYGON_OFFSET_LINE_ENABLED:
                            break;
                        case gl::state::EXTENDED_DIRTY_BIT_SHADER_DERIVATIVE_HINT:
                            break;
                        case gl::state::EXTENDED_DIRTY_BIT_SHADING_RATE_QCOM:
                            break;
                        case gl::state::EXTENDED_DIRTY_BIT_SHADING_RATE_EXT:
                            break;
                        case gl::state::EXTENDED_DIRTY_BIT_LOGIC_OP_ENABLED:
                            break;
                        case gl::state::EXTENDED_DIRTY_BIT_LOGIC_OP:
                            break;
                        case gl::state::EXTENDED_DIRTY_BIT_BLEND_ADVANCED_COHERENT:
                            break;
                        case gl::state::EXTENDED_DIRTY_BIT_FETCH_PER_SAMPLE_ENABLED:
                            break;
                        default:
                            UNREACHABLE();
                    }
                }
            }
            break;

            default:
                UNREACHABLE();
                break;
        }
    }

    return angle::Result::Continue;
}

void ContextWgpu::updatePipelineColorMasks()
{

    FramebufferWgpu *framebufferWgpu      = webgpu::GetImpl(mState.getDrawFramebuffer());
    gl::DrawBufferMask enabledDrawBuffers = framebufferWgpu->getState().getEnabledDrawBuffers();

    bool changed = false;

    const gl::BlendStateExt &blendStateExt = mState.getBlendStateExt();
    for (size_t i = 0; i < blendStateExt.getDrawBufferCount(); i++)
    {
        bool r, g, b, a;
        if (enabledDrawBuffers.test(i))
        {
            blendStateExt.getColorMaskIndexed(i, &r, &g, &b, &a);
        }
        else
        {
            // Disabled draw buffers just have their color mask set to 0.
            r = 0;
            g = 0;
            b = 0;
            a = 0;
        }
        changed = mRenderPipelineDesc.setColorWriteMask(i, r, g, b, a) || changed;
    }

    if (changed)
    {
        invalidateCurrentRenderPipeline();
    }
}

GLint ContextWgpu::getGPUDisjoint()
{
    return 0;
}

GLint64 ContextWgpu::getTimestamp()
{
    return 0;
}

angle::Result ContextWgpu::onMakeCurrent(const gl::Context *context)
{
    return angle::Result::Continue;
}

gl::Caps ContextWgpu::getNativeCaps() const
{
    return mDisplay->getGLCaps();
}

const gl::TextureCapsMap &ContextWgpu::getNativeTextureCaps() const
{
    return mDisplay->getGLTextureCaps();
}

const gl::Extensions &ContextWgpu::getNativeExtensions() const
{
    return mDisplay->getGLExtensions();
}

const gl::Limitations &ContextWgpu::getNativeLimitations() const
{
    return mDisplay->getGLLimitations();
}

const ShPixelLocalStorageOptions &ContextWgpu::getNativePixelLocalStorageOptions() const
{
    return mDisplay->getPLSOptions();
}

CompilerImpl *ContextWgpu::createCompiler()
{
    return new CompilerWgpu();
}

ShaderImpl *ContextWgpu::createShader(const gl::ShaderState &data)
{
    return new ShaderWgpu(data);
}

ProgramImpl *ContextWgpu::createProgram(const gl::ProgramState &data)
{
    return new ProgramWgpu(data);
}

ProgramExecutableImpl *ContextWgpu::createProgramExecutable(const gl::ProgramExecutable *executable)
{
    return new ProgramExecutableWgpu(executable);
}

FramebufferImpl *ContextWgpu::createFramebuffer(const gl::FramebufferState &data)
{
    return new FramebufferWgpu(data);
}

TextureImpl *ContextWgpu::createTexture(const gl::TextureState &state)
{
    return new TextureWgpu(state);
}

RenderbufferImpl *ContextWgpu::createRenderbuffer(const gl::RenderbufferState &state)
{
    return new RenderbufferWgpu(state);
}

BufferImpl *ContextWgpu::createBuffer(const gl::BufferState &state)
{
    return new BufferWgpu(state);
}

VertexArrayImpl *ContextWgpu::createVertexArray(const gl::VertexArrayState &data,
                                                const gl::VertexArrayBuffers &vertexArrayBuffers)
{
    return new VertexArrayWgpu(data, vertexArrayBuffers);
}

QueryImpl *ContextWgpu::createQuery(gl::QueryType type)
{
    return new QueryWgpu(type);
}

FenceNVImpl *ContextWgpu::createFenceNV()
{
    return new FenceNVWgpu();
}

SyncImpl *ContextWgpu::createSync()
{
    return new SyncWgpu();
}

TransformFeedbackImpl *ContextWgpu::createTransformFeedback(const gl::TransformFeedbackState &state)
{
    return new TransformFeedbackWgpu(state);
}

SamplerImpl *ContextWgpu::createSampler(const gl::SamplerState &state)
{
    return new SamplerWgpu(state);
}

ProgramPipelineImpl *ContextWgpu::createProgramPipeline(const gl::ProgramPipelineState &state)
{
    return new ProgramPipelineWgpu(state);
}

MemoryObjectImpl *ContextWgpu::createMemoryObject()
{
    UNREACHABLE();
    return nullptr;
}

SemaphoreImpl *ContextWgpu::createSemaphore()
{
    UNREACHABLE();
    return nullptr;
}

angle::Result ContextWgpu::dispatchCompute(const gl::Context *context,
                                           GLuint numGroupsX,
                                           GLuint numGroupsY,
                                           GLuint numGroupsZ)
{
    return angle::Result::Continue;
}

angle::Result ContextWgpu::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
{
    return angle::Result::Continue;
}

angle::Result ContextWgpu::memoryBarrier(const gl::Context *context, GLbitfield barriers)
{
    return angle::Result::Continue;
}

angle::Result ContextWgpu::memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers)
{
    return angle::Result::Continue;
}

void ContextWgpu::handleError(GLenum errorCode,
                              const char *message,
                              const char *file,
                              const char *function,
                              unsigned int line)
{
    std::stringstream errorStream;
    errorStream << "Internal Wgpu back-end error: " << message << ".";
    mErrors->handleError(errorCode, errorStream.str().c_str(), file, function, line);
}

angle::Result ContextWgpu::startRenderPass(const webgpu::PackedRenderPassDescriptor &desc)
{
    const DawnProcTable *wgpu = webgpu::GetProcs(this);

    ensureCommandEncoderCreated();

    mCurrentRenderPass = webgpu::CreateRenderPass(wgpu, mCurrentCommandEncoder, desc);
    mDirtyBits |= mNewRenderPassDirtyBits;

    return angle::Result::Continue;
}

angle::Result ContextWgpu::endRenderPass(webgpu::RenderPassClosureReason closureReason)
{
    if (mCurrentRenderPass)
    {
        const DawnProcTable *wgpu = webgpu::GetProcs(this);

        const char *reasonText = kRenderPassClosureReason[closureReason];
        ASSERT(reasonText);

        if (mCommandBuffer.hasCommands())
        {
            ANGLE_WGPU_SCOPED_DEBUG_TRY(this,
                                        mCommandBuffer.recordCommands(wgpu, mCurrentRenderPass));
            mCommandBuffer.clear();
        }

        wgpu->renderPassEncoderEnd(mCurrentRenderPass.get());
        mCurrentRenderPass = nullptr;
    }

    mDirtyBits.set(DIRTY_BIT_RENDER_PASS);

    return angle::Result::Continue;
}

angle::Result ContextWgpu::setupDraw(const gl::Context *context,
                                     gl::PrimitiveMode mode,
                                     GLint firstVertexOrInvalid,
                                     GLsizei vertexOrIndexCount,
                                     GLsizei instanceCount,
                                     gl::DrawElementsType indexTypeOrInvalid,
                                     const void *indices,
                                     GLint baseVertex,
                                     uint32_t *outFirstIndex,
                                     uint32_t *indexCountOut)
{
    gl::DrawElementsType dstIndexTypeOrInvalid = indexTypeOrInvalid;
    if (mode == gl::PrimitiveMode::LineLoop &&
        dstIndexTypeOrInvalid == gl::DrawElementsType::InvalidEnum)
    {
        if (vertexOrIndexCount >= std::numeric_limits<unsigned short>::max())
        {
            dstIndexTypeOrInvalid = gl::DrawElementsType::UnsignedInt;
        }
        else
        {
            dstIndexTypeOrInvalid = gl::DrawElementsType::UnsignedShort;
        }
    }

    if (mRenderPipelineDesc.setPrimitiveMode(mode, dstIndexTypeOrInvalid))
    {
        invalidateCurrentRenderPipeline();
    }

    ProgramExecutableWgpu *executableWgpu = webgpu::GetImpl(mState.getProgramExecutable());
    if (executableWgpu->checkDirtyUniforms() || executableWgpu->hasDirtySamplerBindings())
    {
        mDirtyBits.set(DIRTY_BIT_BIND_GROUPS);
    }

    const void *adjustedIndicesPtr = indices;
    if (mState.areClientArraysEnabled())
    {
        VertexArrayWgpu *vertexArrayWgpu = GetImplAs<VertexArrayWgpu>(mState.getVertexArray());
        // Pass in original indexTypeOrInvalid into syncClientArrays because the method will need to
        // determine if the original draw call was a DrawElements or DrawArrays call.
        ANGLE_TRY(vertexArrayWgpu->syncClientArrays(
            context, mState.getProgramExecutable()->getActiveAttribLocationsMask(), mode,
            firstVertexOrInvalid, vertexOrIndexCount, instanceCount, indexTypeOrInvalid, indices,
            baseVertex, mState.isPrimitiveRestartEnabled(), &adjustedIndicesPtr, indexCountOut));
    }

    bool reAddDirtyIndexBufferBit = false;
    if (dstIndexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
    {
        *outFirstIndex =
            gl_wgpu::GetFirstIndexForDrawCall(dstIndexTypeOrInvalid, adjustedIndicesPtr);
        if (mCurrentIndexBufferType != dstIndexTypeOrInvalid)
        {
            invalidateIndexBuffer();
        }
    }

    if (mDirtyBits.any())
    {
        for (DirtyBits::Iterator dirtyBitIter = mDirtyBits.begin();
             dirtyBitIter != mDirtyBits.end(); ++dirtyBitIter)
        {
            size_t dirtyBit = *dirtyBitIter;
            switch (dirtyBit)
            {
                case DIRTY_BIT_RENDER_PIPELINE_DESC:
                    ANGLE_TRY(handleDirtyRenderPipelineDesc(&dirtyBitIter));
                    break;

                case DIRTY_BIT_RENDER_PASS:
                    ANGLE_TRY(handleDirtyRenderPass(&dirtyBitIter));
                    break;

                case DIRTY_BIT_RENDER_PIPELINE_BINDING:
                    ANGLE_TRY(handleDirtyRenderPipelineBinding(&dirtyBitIter));
                    break;

                case DIRTY_BIT_VIEWPORT:
                    ANGLE_TRY(handleDirtyViewport(&dirtyBitIter));
                    break;

                case DIRTY_BIT_SCISSOR:
                    ANGLE_TRY(handleDirtyScissor(&dirtyBitIter));
                    break;

                case DIRTY_BIT_STENCIL_REF:
                    ANGLE_TRY(handleDirtyStencilRef(&dirtyBitIter));
                    break;

                case DIRTY_BIT_BLEND_CONSTANT:
                    ANGLE_TRY(handleDirtyBlendConstant(&dirtyBitIter));
                    break;

                case DIRTY_BIT_VERTEX_BUFFERS:
                    ANGLE_TRY(handleDirtyVertexBuffers(mDirtyVertexBuffers, &dirtyBitIter));
                    mDirtyVertexBuffers.reset();
                    break;

                case DIRTY_BIT_INDEX_BUFFER:
                    if (dstIndexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
                    {
                        ANGLE_TRY(handleDirtyIndexBuffer(dstIndexTypeOrInvalid, &dirtyBitIter));
                    }
                    else
                    {
                        // If this is not an indexed draw call, don't sync the index buffer. Save it
                        // for a future indexed draw call when we know what index type to use
                        reAddDirtyIndexBufferBit = true;
                    }
                    break;
                case DIRTY_BIT_DRIVER_UNIFORMS:
                    ANGLE_TRY(handleDirtyDriverUniforms(&dirtyBitIter));
                    break;
                case DIRTY_BIT_BIND_GROUPS:
                    ANGLE_TRY(handleDirtyBindGroups(&dirtyBitIter));
                    break;
                default:
                    UNREACHABLE();
                    break;
            }
        }

        if (reAddDirtyIndexBufferBit)
        {
            // Re-add the index buffer dirty bit for a future indexed draw call.
            mDirtyBits.reset(DIRTY_BIT_INDEX_BUFFER);
        }

        mDirtyBits.reset();
    }

    return angle::Result::Continue;
}

angle::Result ContextWgpu::handleDirtyRenderPipelineDesc(DirtyBits::Iterator *dirtyBitsIterator)
{
    ASSERT(mState.getProgramExecutable() != nullptr);
    ProgramExecutableWgpu *executable = webgpu::GetImpl(mState.getProgramExecutable());
    ASSERT(executable);

    webgpu::RenderPipelineHandle previousPipeline = std::move(mCurrentGraphicsPipeline);
    ANGLE_TRY(executable->getRenderPipeline(this, mRenderPipelineDesc, &mCurrentGraphicsPipeline));
    if (mCurrentGraphicsPipeline != previousPipeline)
    {
        dirtyBitsIterator->setLaterBit(DIRTY_BIT_RENDER_PIPELINE_BINDING);
    }
    mCurrentRenderPipelineAllAttributes =
        executable->getExecutable()->getActiveAttribLocationsMask();

    return angle::Result::Continue;
}

angle::Result ContextWgpu::handleDirtyRenderPipelineBinding(DirtyBits::Iterator *dirtyBitsIterator)
{
    ASSERT(mCurrentGraphicsPipeline);
    mCommandBuffer.setPipeline(mCurrentGraphicsPipeline);
    return angle::Result::Continue;
}

angle::Result ContextWgpu::handleDirtyViewport(DirtyBits::Iterator *dirtyBitsIterator)
{
    const gl::Framebuffer *framebuffer = mState.getDrawFramebuffer();
    const gl::Extents &framebufferSize = framebuffer->getExtents();
    const gl::Rectangle framebufferRect(0, 0, framebufferSize.width, framebufferSize.height);

    gl::Rectangle clampedViewport;
    if (!ClipRectangle(mState.getViewport(), framebufferRect, &clampedViewport))
    {
        clampedViewport = gl::Rectangle(0, 0, 1, 1);
    }

    float depthMin = mState.getNearPlane();
    float depthMax = mState.getFarPlane();

    // This clamping should be done by the front end. WebGPU requires values in this range.
    ASSERT(depthMin >= 0 && depthMin <= 1);
    ASSERT(depthMin >= 0 && depthMin <= 1);

    // WebGPU requires that the maxDepth is at least minDepth. WebGL requires the same but core GL
    // ES does not.
    if (depthMin > depthMax)
    {
        UNIMPLEMENTED();
    }

    bool isDefaultViewport = (clampedViewport == framebufferRect) && depthMin == 0 && depthMax == 1;
    if (isDefaultViewport && !mCommandBuffer.hasSetViewportCommand())
    {
        // Each render pass has a default viewport set equal to the size of the render targets. We
        // can skip setting the viewport.
        return angle::Result::Continue;
    }

    FramebufferWgpu *drawFramebufferWgpu = webgpu::GetImpl(mState.getDrawFramebuffer());
    if (drawFramebufferWgpu->flipY())
    {
        clampedViewport.y =
            drawFramebufferWgpu->getState().getDimensions().height - clampedViewport.y1();
    }

    ASSERT(mCurrentGraphicsPipeline);
    mCommandBuffer.setViewport(clampedViewport.x, clampedViewport.y, clampedViewport.width,
                               clampedViewport.height, depthMin, depthMax);

    return angle::Result::Continue;
}

angle::Result ContextWgpu::handleDirtyScissor(DirtyBits::Iterator *dirtyBitsIterator)
{
    const gl::Framebuffer *framebuffer = mState.getDrawFramebuffer();
    const gl::Extents &framebufferSize = framebuffer->getExtents();
    const gl::Rectangle framebufferRect(0, 0, framebufferSize.width, framebufferSize.height);

    gl::Rectangle clampedScissor = ClipRectToScissor(mState, framebufferRect, false);

    bool isDefaultScissor = clampedScissor == framebufferRect;
    if (isDefaultScissor && !mCommandBuffer.hasSetScissorCommand())
    {
        // Each render pass has a default scissor set equal to the size of the render targets. We
        // can skip setting the scissor.
        return angle::Result::Continue;
    }

    FramebufferWgpu *framebufferWgpu = webgpu::GetImpl(framebuffer);
    if (framebufferWgpu->flipY())
    {
        clampedScissor.y = framebufferWgpu->getState().getDimensions().height - clampedScissor.y -
                           clampedScissor.height;
    }

    ASSERT(mCurrentGraphicsPipeline);
    mCommandBuffer.setScissorRect(clampedScissor.x, clampedScissor.y, clampedScissor.width,
                                  clampedScissor.height);
    return angle::Result::Continue;
}

angle::Result ContextWgpu::handleDirtyStencilRef(DirtyBits::Iterator *dirtyBitsIterator)
{
    if (!mState.getDepthStencilState().stencilTest)
    {
        // The stencil ref doesn't matter when stencil testing is disabled.
        return angle::Result::Continue;
    }

    const int refVal = mState.getStencilRef();

    // This backend sets `noSeparateStencilRefsAndMasks`, and WebGPU does not
    // support different ref values for front and back.
    ASSERT(refVal == mState.getStencilBackRef());

    const bool isDefaultStencilValue = refVal == 0;
    if (!mCommandBuffer.hasSetStencilRefCommand() && isDefaultStencilValue)
    {
        // Each render pass has a default stencil reference set to zero. We can skip setting it.
        return angle::Result::Continue;
    }

    mCommandBuffer.setStencilReference(mState.getStencilRef());
    return angle::Result::Continue;
}

angle::Result ContextWgpu::handleDirtyBlendConstant(DirtyBits::Iterator *dirtyBitsIterator)
{
    const gl::ColorF &blendColor = mState.getBlendColor();

    bool isDefaultBlendConstant = blendColor.red == 0 && blendColor.green == 0 &&
                                  blendColor.blue == 0 && blendColor.alpha == 0;
    if (isDefaultBlendConstant && !mCommandBuffer.hasSetBlendConstantCommand())
    {
        // Each render pass has a default blend constant set to all zeroes. We can skip setting it.
        return angle::Result::Continue;
    }

    ASSERT(mCurrentGraphicsPipeline);
    mCommandBuffer.setBlendConstant(blendColor.red, blendColor.green, blendColor.blue,
                                    blendColor.alpha);
    return angle::Result::Continue;
}

angle::Result ContextWgpu::handleDirtyRenderPass(DirtyBits::Iterator *dirtyBitsIterator)
{
    FramebufferWgpu *drawFramebufferWgpu = webgpu::GetImpl(mState.getDrawFramebuffer());
    ANGLE_TRY(drawFramebufferWgpu->startNewRenderPass(this));
    dirtyBitsIterator->setLaterBits(mNewRenderPassDirtyBits);
    mDirtyVertexBuffers = mCurrentRenderPipelineAllAttributes;
    return angle::Result::Continue;
}

angle::Result ContextWgpu::handleDirtyVertexBuffers(const gl::AttributesMask &slots,
                                                    DirtyBits::Iterator *dirtyBitsIterator)
{
    VertexArrayWgpu *vertexArrayWgpu = GetImplAs<VertexArrayWgpu>(mState.getVertexArray());
    for (size_t slot : slots)
    {
        const VertexBufferWithOffset &buffer = vertexArrayWgpu->getVertexBuffer(slot);
        if (!buffer.buffer)
        {
            // Missing default attribute support
            ASSERT(!mState.getVertexArray()->getVertexAttribute(slot).enabled);
            UNIMPLEMENTED();
            continue;
        }
        if (buffer.buffer->getMappedState())
        {
            ANGLE_TRY(buffer.buffer->unmap());
        }
        mCommandBuffer.setVertexBuffer(static_cast<uint32_t>(slot), buffer.buffer->getBuffer(),
                                       buffer.offset, WGPU_WHOLE_SIZE);
    }
    return angle::Result::Continue;
}

angle::Result ContextWgpu::handleDirtyIndexBuffer(gl::DrawElementsType indexType,
                                                  DirtyBits::Iterator *dirtyBitsIterator)
{
    VertexArrayWgpu *vertexArrayWgpu = GetImplAs<VertexArrayWgpu>(mState.getVertexArray());
    webgpu::BufferHelper *buffer     = vertexArrayWgpu->getIndexBuffer();
    ASSERT(buffer);
    if (buffer->getMappedState())
    {
        ANGLE_TRY(buffer->unmap());
    }
    mCommandBuffer.setIndexBuffer(buffer->getBuffer(),
                                  static_cast<WGPUIndexFormat>(gl_wgpu::GetIndexFormat(indexType)),
                                  0, -1);
    mCurrentIndexBufferType = indexType;
    return angle::Result::Continue;
}

angle::Result ContextWgpu::handleDirtyBindGroups(DirtyBits::Iterator *dirtyBitsIterator)
{
    ProgramExecutableWgpu *executableWgpu = webgpu::GetImpl(mState.getProgramExecutable());
    webgpu::BindGroupHandle defaultUniformBindGroup;
    ANGLE_TRY(executableWgpu->updateUniformsAndGetBindGroup(this, &defaultUniformBindGroup));
    mCommandBuffer.setBindGroup(sh::kDefaultUniformBlockBindGroup, defaultUniformBindGroup);

    webgpu::BindGroupHandle samplerAndTextureBindGroup;
    ANGLE_TRY(executableWgpu->getSamplerAndTextureBindGroup(this, &samplerAndTextureBindGroup));
    mCommandBuffer.setBindGroup(sh::kTextureAndSamplerBindGroup, samplerAndTextureBindGroup);

    // Creating the driver uniform bind group is handled by handleDirtyDriverUniforms().
    mCommandBuffer.setBindGroup(sh::kDriverUniformBindGroup, mDriverUniformsBindGroup);

    return angle::Result::Continue;
}

angle::Result ContextWgpu::handleDirtyDriverUniforms(DirtyBits::Iterator *dirtyBitsIterator)
{
    const DawnProcTable *wgpu = webgpu::GetProcs(this);

    DriverUniforms newDriverUniforms;
    memset(&newDriverUniforms, 0, sizeof(newDriverUniforms));

    newDriverUniforms.depthRange[0] = mState.getNearPlane();
    newDriverUniforms.depthRange[1] = mState.getFarPlane();

    FramebufferWgpu *drawFramebufferWgpu = webgpu::GetImpl(mState.getDrawFramebuffer());

    newDriverUniforms.renderArea = drawFramebufferWgpu->getState().getDimensions().height << 16 |
                                   drawFramebufferWgpu->getState().getDimensions().width;

    const float flipX        = 1.0f;
    const float flipY        = drawFramebufferWgpu->flipY() ? -1.0f : 1.0f;
    newDriverUniforms.flipXY = gl::PackSnorm4x8(
        flipX, flipY, flipX, mState.getClipOrigin() == gl::ClipOrigin::LowerLeft ? -flipY : flipY);

    // gl_ClipDistance
    const uint32_t enabledClipDistances = mState.getEnabledClipDistances().bits();
    ASSERT((enabledClipDistances & ~sh::vk::kDriverUniformsMiscEnabledClipPlanesMask) == 0);

    // GL_CLIP_DEPTH_MODE_EXT
    const uint32_t transformDepth = !mState.isClipDepthModeZeroToOne();
    ASSERT((transformDepth & ~sh::vk::kDriverUniformsMiscTransformDepthMask) == 0);

    // GL_SAMPLE_ALPHA_TO_COVERAGE
    const uint32_t alphaToCoverage = mState.isSampleAlphaToCoverageEnabled();
    ASSERT((alphaToCoverage & ~sh::vk::kDriverUniformsMiscAlphaToCoverageMask) == 0);

    newDriverUniforms.misc =
        (enabledClipDistances << sh::vk::kDriverUniformsMiscEnabledClipPlanesOffset) |
        (transformDepth << sh::vk::kDriverUniformsMiscTransformDepthOffset) |
        (alphaToCoverage << sh::vk::kDriverUniformsMiscAlphaToCoverageOffset);

    // If no change to driver uniforms, return early.
    if (ANGLE_UNSAFE_TODO(memcmp(&newDriverUniforms, &mDriverUniforms, sizeof(DriverUniforms))) ==
        0)
    {
        return angle::Result::Continue;
    }

    // Cache the uniforms so we can check for changes later.
    ANGLE_UNSAFE_TODO(memcpy(&mDriverUniforms, &newDriverUniforms, sizeof(DriverUniforms)));

    // Upload the new driver uniforms to a new GPU buffer.
    webgpu::BufferHelper driverUniformBuffer;

    ANGLE_TRY(driverUniformBuffer.initBuffer(wgpu, getDevice(), sizeof(DriverUniforms),
                                             WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst,
                                             webgpu::MapAtCreation::Yes));

    ASSERT(driverUniformBuffer.valid());

    uint8_t *bufferData = driverUniformBuffer.getMapWritePointer(0, sizeof(DriverUniforms));
    ANGLE_UNSAFE_TODO(memcpy(bufferData, &mDriverUniforms, sizeof(DriverUniforms)));

    ANGLE_TRY(driverUniformBuffer.unmap());

    // Now create the bind group containing the driver uniform buffer.
    WGPUBindGroupEntry bindGroupEntry = WGPU_BIND_GROUP_ENTRY_INIT;
    bindGroupEntry.binding = sh::kDriverUniformBlockBinding;
    bindGroupEntry.buffer             = driverUniformBuffer.getBuffer().get();
    bindGroupEntry.offset  = 0;
    bindGroupEntry.size    = sizeof(DriverUniforms);

    WGPUBindGroupDescriptor bindGroupDesc = WGPU_BIND_GROUP_DESCRIPTOR_INIT;
    bindGroupDesc.layout                  = mDriverUniformsBindGroupLayout.get();
    bindGroupDesc.entryCount = 1;
    bindGroupDesc.entries    = &bindGroupEntry;
    mDriverUniformsBindGroup              = webgpu::BindGroupHandle::Acquire(
        wgpu, wgpu->deviceCreateBindGroup(getDevice().get(), &bindGroupDesc));

    // This bind group needs to be updated on the same draw call as the driver uniforms are updated.
    dirtyBitsIterator->setLaterBit(DIRTY_BIT_BIND_GROUPS);

    return angle::Result::Continue;
}

}  // namespace rx
