//
// Copyright 2020 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.
//
// serialize.cpp:
//   ANGLE GL state serialization.
//

#include "libANGLE/capture/serialize.h"
#include "common/unsafe_buffers.h"

#include "common/Color.h"
#include "common/MemoryBuffer.h"
#include "common/angleutils.h"
#include "common/gl_enum_utils.h"
#include "common/serializer/JsonSerializer.h"
#include "libANGLE/Buffer.h"
#include "libANGLE/Caps.h"
#include "libANGLE/Context.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/Query.h"
#include "libANGLE/RefCountObject.h"
#include "libANGLE/ResourceMap.h"
#include "libANGLE/Sampler.h"
#include "libANGLE/State.h"
#include "libANGLE/TransformFeedback.h"
#include "libANGLE/VertexAttribute.h"
#include "libANGLE/angletypes.h"
#include "libANGLE/renderer/FramebufferImpl.h"
#include "libANGLE/renderer/RenderbufferImpl.h"

#include <vector>

#if !ANGLE_CAPTURE_ENABLED
#    error Frame capture must be enabled to build this file.
#endif  // !ANGLE_CAPTURE_ENABLED

// Note: when diagnosing serialization comparison failures, you can disable the unused function
// compiler warning to allow bisecting the comparison function. One first check is to disable
// Framebuffer Attachment pixel comparison which includes the pixel contents of the default FBO.
// ANGLE_DISABLE_UNUSED_FUNCTION_WARNING

namespace angle
{
namespace
{
template <typename ArgT>
std::string ToString(const ArgT &arg)
{
    std::ostringstream strstr;
    strstr << arg;
    return strstr.str();
}

#define ENUM_TO_STRING(C, M) \
    case C ::M:              \
        return #M

const char *InitStateToString(gl::InitState state)
{
    switch (state)
    {
        ENUM_TO_STRING(gl::InitState, Initialized);
        ENUM_TO_STRING(gl::InitState, MayNeedInit);
        default:
            return "invalid";
    }
}

const char *SrgbOverrideToString(gl::SrgbOverride value)
{
    switch (value)
    {
        ENUM_TO_STRING(gl::SrgbOverride, Default);
        ENUM_TO_STRING(gl::SrgbOverride, SRGB);
        default:
            return "invalid";
    }
}

const char *ColorGenericTypeToString(gl::ColorGeneric::Type type)
{
    switch (type)
    {
        ENUM_TO_STRING(gl::ColorGeneric::Type, Float);
        ENUM_TO_STRING(gl::ColorGeneric::Type, Int);
        ENUM_TO_STRING(gl::ColorGeneric::Type, UInt);
        default:
            return "invalid";
    }
}

const char *CompileStatusToString(gl::CompileStatus status)
{
    switch (status)
    {
        ENUM_TO_STRING(gl::CompileStatus, NOT_COMPILED);
        ENUM_TO_STRING(gl::CompileStatus, COMPILE_REQUESTED);
        ENUM_TO_STRING(gl::CompileStatus, COMPILED);
        default:
            return "invalid";
    }
}

#undef ENUM_TO_STRING

class [[nodiscard]] GroupScope
{
  public:
    GroupScope(JsonSerializer *json, const std::string &name) : mJson(json)
    {
        mJson->startGroup(name);
    }

    GroupScope(JsonSerializer *json, const std::string &name, int index) : mJson(json)
    {
        constexpr size_t kBufSize = 255;
        char buf[kBufSize + 1]    = {};
        ANGLE_UNSAFE_TODO(
            snprintf(buf, kBufSize, "%s%s%03d", name.c_str(), name.empty() ? "" : " ", index));
        mJson->startGroup(buf);
    }

    GroupScope(JsonSerializer *json, int index) : GroupScope(json, "", index) {}

    ~GroupScope() { mJson->endGroup(); }

  private:
    JsonSerializer *mJson;
};

void SerializeColorF(JsonSerializer *json, const ColorF &color)
{
    json->addScalar("red", color.red);
    json->addScalar("green", color.green);
    json->addScalar("blue", color.blue);
    json->addScalar("alpha", color.alpha);
}

void SerializeColorFWithGroup(JsonSerializer *json, const char *groupName, const ColorF &color)
{
    GroupScope group(json, groupName);
    SerializeColorF(json, color);
}

void SerializeColorI(JsonSerializer *json, const ColorI &color)
{
    json->addScalar("Red", color.red);
    json->addScalar("Green", color.green);
    json->addScalar("Blue", color.blue);
    json->addScalar("Alpha", color.alpha);
}

void SerializeColorUI(JsonSerializer *json, const ColorUI &color)
{
    json->addScalar("Red", color.red);
    json->addScalar("Green", color.green);
    json->addScalar("Blue", color.blue);
    json->addScalar("Alpha", color.alpha);
}

void SerializeExtents(JsonSerializer *json, const gl::Extents &extents)
{
    json->addScalar("Width", extents.width);
    json->addScalar("Height", extents.height);
    json->addScalar("Depth", extents.depth);
}

template <class ObjectType>
void SerializeOffsetBindingPointerVector(
    JsonSerializer *json,
    const char *groupName,
    const std::vector<gl::OffsetBindingPointer<ObjectType>> &offsetBindingPointerVector)
{
    GroupScope vectorGroup(json, groupName);

    for (size_t i = 0; i < offsetBindingPointerVector.size(); i++)
    {
        GroupScope itemGroup(json, static_cast<int>(i));
        json->addScalar("Value", offsetBindingPointerVector[i].id().value);
        json->addScalar("Offset", offsetBindingPointerVector[i].getOffset());
        json->addScalar("Size", offsetBindingPointerVector[i].getSize());
    }
}

template <class ObjectType>
void SerializeBindingPointerVector(
    JsonSerializer *json,
    const std::vector<gl::BindingPointer<ObjectType>> &bindingPointerVector)
{
    for (size_t i = 0; i < bindingPointerVector.size(); i++)
    {
        const gl::BindingPointer<ObjectType> &obj = bindingPointerVector[i];

        // Do not serialize zero bindings, as this will create unwanted diffs
        if (obj.id().value != 0)
        {
            std::ostringstream s;
            s << std::setfill('0') << std::setw(3) << i;
            json->addScalar(s.str(), obj.id().value);
        }
    }
}

template <class T>
void SerializeRange(JsonSerializer *json, const gl::Range<T> &range)
{
    GroupScope group(json, "Range");
    json->addScalar("Low", range.low());
    json->addScalar("High", range.high());
}

bool IsValidColorAttachmentBinding(GLenum binding, size_t colorAttachmentsCount)
{
    return binding == GL_BACK || (binding >= GL_COLOR_ATTACHMENT0 &&
                                  (binding - GL_COLOR_ATTACHMENT0) < colorAttachmentsCount);
}

void SerializeFormat(JsonSerializer *json, GLenum glFormat)
{
    json->addCString("InternalFormat", gl::GLenumToString(gl::GLESEnum::InternalFormat, glFormat));
}

void SerializeInternalFormat(JsonSerializer *json, const gl::InternalFormat *internalFormat)
{
    SerializeFormat(json, internalFormat->internalFormat);
}

void SerializeANGLEFormat(JsonSerializer *json, const angle::Format *format)
{
    SerializeFormat(json, format->glInternalFormat);
}

void SerializeGLFormat(JsonSerializer *json, const gl::Format &format)
{
    SerializeInternalFormat(json, format.info);
}

Result ReadPixelsFromAttachment(const gl::Context *context,
                                gl::Framebuffer *framebuffer,
                                const gl::FramebufferAttachment &framebufferAttachment,
                                ScratchBuffer *scratchBuffer,
                                MemoryBuffer **pixels)
{
    gl::Extents extents       = framebufferAttachment.getSize();
    GLenum binding            = framebufferAttachment.getBinding();
    gl::InternalFormat format = *framebufferAttachment.getFormat().info;
    if (IsValidColorAttachmentBinding(binding,
                                      framebuffer->getState().getColorAttachments().size()))
    {
        format = framebuffer->getImplementation()->getImplementationColorReadFormat(context);
    }
    ANGLE_CHECK_GL_ALLOC(const_cast<gl::Context *>(context),
                         scratchBuffer->getInitialized(
                             format.pixelBytes * extents.width * extents.height, pixels, 0));
    ANGLE_TRY(framebuffer->readPixels(context, gl::Rectangle{0, 0, extents.width, extents.height},
                                      format.format, format.type, gl::PixelPackState{}, nullptr,
                                      (*pixels)->data()));
    return Result::Continue;
}
void SerializeImageIndex(JsonSerializer *json, const gl::ImageIndex &imageIndex)
{
    GroupScope group(json, "Image");
    json->addString("ImageType", ToString(imageIndex.getType()));
    json->addScalar("LevelIndex", imageIndex.getLevelIndex());
    json->addScalar("LayerIndex", imageIndex.getLayerIndex());
    json->addScalar("LayerCount", imageIndex.getLayerCount());
}

Result SerializeFramebufferAttachment(const gl::Context *context,
                                      JsonSerializer *json,
                                      ScratchBuffer *scratchBuffer,
                                      gl::Framebuffer *framebuffer,
                                      const gl::FramebufferAttachment &framebufferAttachment,
                                      gl::GLESEnum enumGroup)
{
    if (framebufferAttachment.type() == GL_TEXTURE ||
        framebufferAttachment.type() == GL_RENDERBUFFER)
    {
        json->addScalar("AttachedResourceID", framebufferAttachment.id());
    }
    json->addCString(
        "Type", gl::GLenumToString(gl::GLESEnum::ObjectIdentifier, framebufferAttachment.type()));
    // serialize target variable
    json->addString("Binding", gl::GLenumToString(enumGroup, framebufferAttachment.getBinding()));
    if (framebufferAttachment.type() == GL_TEXTURE)
    {
        SerializeImageIndex(json, framebufferAttachment.getTextureImageIndex());
    }
    json->addScalar("NumViews", framebufferAttachment.getNumViews());
    json->addScalar("Multiview", framebufferAttachment.isMultiview());
    json->addScalar("ViewIndex", framebufferAttachment.getBaseViewIndex());
    json->addScalar("Samples", framebufferAttachment.getRenderToTextureSamples());

    // Need to resolve the size before getting it below.
    ANGLE_TRY(framebufferAttachment.ensureSizeResolved(context));

    {
        GroupScope extentsGroup(json, "Extents");
        SerializeExtents(json, framebufferAttachment.getSize());
    }

    if (framebufferAttachment.type() != GL_TEXTURE &&
        framebufferAttachment.type() != GL_RENDERBUFFER)
    {
        GLenum prevReadBufferState = framebuffer->getReadBufferState();
        GLenum binding             = framebufferAttachment.getBinding();
        if (IsValidColorAttachmentBinding(binding,
                                          framebuffer->getState().getColorAttachments().size()))
        {
            framebuffer->setReadBuffer(framebufferAttachment.getBinding());
            ANGLE_TRY(framebuffer->syncState(context, GL_FRAMEBUFFER, gl::Command::Other));
        }

        if (framebufferAttachment.initState() == gl::InitState::Initialized)
        {
            MemoryBuffer *pixelsPtr = nullptr;
            ANGLE_TRY(ReadPixelsFromAttachment(context, framebuffer, framebufferAttachment,
                                               scratchBuffer, &pixelsPtr));
            json->addBlob("Data", *pixelsPtr);
        }
        else
        {
            json->addCString("Data", "Not initialized");
        }
        // Reset framebuffer state
        framebuffer->setReadBuffer(prevReadBufferState);
    }
    return Result::Continue;
}

Result SerializeFramebufferState(const gl::Context *context,
                                 JsonSerializer *json,
                                 ScratchBuffer *scratchBuffer,
                                 gl::Framebuffer *framebuffer,
                                 const gl::FramebufferState &framebufferState)
{
    GroupScope group(json, "Framebuffer", framebufferState.id().value);

    json->addString("Label", framebufferState.getLabel());
    json->addVector("DrawStates", framebufferState.getDrawBufferStates());
    json->addScalar("ReadBufferState", framebufferState.getReadBufferState());
    json->addScalar("DefaultWidth", framebufferState.getDefaultWidth());
    json->addScalar("DefaultHeight", framebufferState.getDefaultHeight());
    json->addScalar("DefaultSamples", framebufferState.getDefaultSamples());
    json->addScalar("DefaultFixedSampleLocation",
                    framebufferState.getDefaultFixedSampleLocations());
    json->addScalar("DefaultLayers", framebufferState.getDefaultLayers());
    json->addScalar("FlipY", framebufferState.getFlipY());

    {
        GroupScope attachmentsGroup(json, "Attachments");
        const gl::DrawBuffersVector<gl::FramebufferAttachment> &colorAttachments =
            framebufferState.getColorAttachments();
        for (size_t attachmentIndex = 0; attachmentIndex < colorAttachments.size();
             ++attachmentIndex)
        {
            const gl::FramebufferAttachment &colorAttachment = colorAttachments[attachmentIndex];
            if (colorAttachment.isAttached())
            {
                GroupScope colorAttachmentgroup(json, "ColorAttachment",
                                                static_cast<int>(attachmentIndex));
                ANGLE_TRY(SerializeFramebufferAttachment(context, json, scratchBuffer, framebuffer,
                                                         colorAttachment,
                                                         gl::GLESEnum::ColorBuffer));
            }
        }
        if (framebuffer->getDepthStencilAttachment())
        {
            GroupScope dsAttachmentgroup(json, "DepthStencilAttachment");
            ANGLE_TRY(SerializeFramebufferAttachment(context, json, scratchBuffer, framebuffer,
                                                     *framebuffer->getDepthStencilAttachment(),
                                                     gl::GLESEnum::AllEnums));
        }
        else
        {
            if (framebuffer->getDepthAttachment())
            {
                GroupScope depthAttachmentgroup(json, "DepthAttachment");
                ANGLE_TRY(SerializeFramebufferAttachment(context, json, scratchBuffer, framebuffer,
                                                         *framebuffer->getDepthAttachment(),
                                                         gl::GLESEnum::FramebufferAttachment));
            }
            if (framebuffer->getStencilAttachment())
            {
                GroupScope stencilAttachmengroup(json, "StencilAttachment");
                ANGLE_TRY(SerializeFramebufferAttachment(context, json, scratchBuffer, framebuffer,
                                                         *framebuffer->getStencilAttachment(),
                                                         gl::GLESEnum::AllEnums));
            }
        }
    }
    return Result::Continue;
}

Result SerializeFramebuffer(const gl::Context *context,
                            JsonSerializer *json,
                            ScratchBuffer *scratchBuffer,
                            gl::Framebuffer *framebuffer)
{
    return SerializeFramebufferState(context, json, scratchBuffer, framebuffer,
                                     framebuffer->getState());
}

void SerializeRasterizerState(JsonSerializer *json, const gl::RasterizerState &rasterizerState)
{
    GroupScope group(json, "Rasterizer");
    json->addScalar("CullFace", rasterizerState.cullFace);
    json->addString("CullMode", ToString(rasterizerState.cullMode));
    json->addScalar("FrontFace", rasterizerState.frontFace);
    json->addString("PolygonMode", ToString(rasterizerState.polygonMode));
    json->addScalar("PolygonOffsetPoint", rasterizerState.polygonOffsetPoint);
    json->addScalar("PolygonOffsetLine", rasterizerState.polygonOffsetLine);
    json->addScalar("PolygonOffsetFill", rasterizerState.polygonOffsetFill);
    json->addScalar("PolygonOffsetFactor", rasterizerState.polygonOffsetFactor);
    json->addScalar("PolygonOffsetUnits", rasterizerState.polygonOffsetUnits);
    json->addScalar("PolygonOffsetClamp", rasterizerState.polygonOffsetClamp);
    json->addScalar("DepthClamp", rasterizerState.depthClamp);
    json->addScalar("PointDrawMode", rasterizerState.pointDrawMode);
    json->addScalar("MultiSample", rasterizerState.multiSample);
    json->addScalar("RasterizerDiscard", rasterizerState.rasterizerDiscard);
    json->addScalar("Dither", rasterizerState.dither);
}

void SerializeRectangle(JsonSerializer *json,
                        const std::string &name,
                        const gl::Rectangle &rectangle)
{
    GroupScope group(json, name);
    json->addScalar("x", rectangle.x);
    json->addScalar("y", rectangle.y);
    json->addScalar("w", rectangle.width);
    json->addScalar("h", rectangle.height);
}

void SerializeBlendStateExt(JsonSerializer *json, const gl::BlendStateExt &blendStateExt)
{
    GroupScope group(json, "BlendStateExt");
    json->addScalar("DrawBufferCount", blendStateExt.getDrawBufferCount());
    json->addScalar("EnableMask", blendStateExt.getEnabledMask().bits());
    json->addScalar("DstColor", blendStateExt.getDstColorBits());
    json->addScalar("DstAlpha", blendStateExt.getDstAlphaBits());
    json->addScalar("SrcColor", blendStateExt.getSrcColorBits());
    json->addScalar("SrcAlpha", blendStateExt.getSrcAlphaBits());
    json->addScalar("EquationColor", blendStateExt.getEquationColorBits());
    json->addScalar("EquationAlpha", blendStateExt.getEquationAlphaBits());
    json->addScalar("ColorMask", blendStateExt.getColorMaskBits());
}

void SerializeDepthStencilState(JsonSerializer *json,
                                const gl::DepthStencilState &depthStencilState)
{
    GroupScope group(json, "DepthStencilState");
    json->addScalar("DepthTest", depthStencilState.depthTest);
    json->addScalar("DepthFunc", depthStencilState.depthFunc);
    json->addScalar("DepthMask", depthStencilState.depthMask);
    json->addScalar("StencilTest", depthStencilState.stencilTest);
    json->addScalar("StencilFunc", depthStencilState.stencilFunc);
    json->addScalar("StencilMask", depthStencilState.stencilMask);
    json->addScalar("StencilFail", depthStencilState.stencilFail);
    json->addScalar("StencilPassDepthFail", depthStencilState.stencilPassDepthFail);
    json->addScalar("StencilPassDepthPass", depthStencilState.stencilPassDepthPass);
    json->addScalar("StencilWritemask", depthStencilState.stencilWritemask);
    json->addScalar("StencilBackFunc", depthStencilState.stencilBackFunc);
    json->addScalar("StencilBackMask", depthStencilState.stencilBackMask);
    json->addScalar("StencilBackFail", depthStencilState.stencilBackFail);
    json->addScalar("StencilBackPassDepthFail", depthStencilState.stencilBackPassDepthFail);
    json->addScalar("StencilBackPassDepthPass", depthStencilState.stencilBackPassDepthPass);
    json->addScalar("StencilBackWritemask", depthStencilState.stencilBackWritemask);
}

void SerializeVertexAttribCurrentValueData(
    JsonSerializer *json,
    const gl::VertexAttribCurrentValueData &vertexAttribCurrentValueData)
{
    ASSERT(vertexAttribCurrentValueData.Type == gl::VertexAttribType::Float ||
           vertexAttribCurrentValueData.Type == gl::VertexAttribType::Int ||
           vertexAttribCurrentValueData.Type == gl::VertexAttribType::UnsignedInt);
    if (vertexAttribCurrentValueData.Type == gl::VertexAttribType::Float)
    {
        json->addScalar("0", vertexAttribCurrentValueData.Values.FloatValues[0]);
        json->addScalar("1", vertexAttribCurrentValueData.Values.FloatValues[1]);
        json->addScalar("2", vertexAttribCurrentValueData.Values.FloatValues[2]);
        json->addScalar("3", vertexAttribCurrentValueData.Values.FloatValues[3]);
    }
    else if (vertexAttribCurrentValueData.Type == gl::VertexAttribType::Int)
    {
        json->addScalar("0", vertexAttribCurrentValueData.Values.IntValues[0]);
        json->addScalar("1", vertexAttribCurrentValueData.Values.IntValues[1]);
        json->addScalar("2", vertexAttribCurrentValueData.Values.IntValues[2]);
        json->addScalar("3", vertexAttribCurrentValueData.Values.IntValues[3]);
    }
    else
    {
        json->addScalar("0", vertexAttribCurrentValueData.Values.UnsignedIntValues[0]);
        json->addScalar("1", vertexAttribCurrentValueData.Values.UnsignedIntValues[1]);
        json->addScalar("2", vertexAttribCurrentValueData.Values.UnsignedIntValues[2]);
        json->addScalar("3", vertexAttribCurrentValueData.Values.UnsignedIntValues[3]);
    }
}

void SerializePixelPackState(JsonSerializer *json, const gl::PixelPackState &pixelPackState)
{
    GroupScope group(json, "PixelPackState");
    json->addScalar("Alignment", pixelPackState.alignment);
    json->addScalar("RowLength", pixelPackState.rowLength);
    json->addScalar("SkipRows", pixelPackState.skipRows);
    json->addScalar("SkipPixels", pixelPackState.skipPixels);
    json->addScalar("ImageHeight", pixelPackState.imageHeight);
    json->addScalar("SkipImages", pixelPackState.skipImages);
    json->addScalar("ReverseRowOrder", pixelPackState.reverseRowOrder);
}

void SerializePixelUnpackState(JsonSerializer *json, const gl::PixelUnpackState &pixelUnpackState)
{
    GroupScope group(json, "PixelUnpackState");
    json->addScalar("Alignment", pixelUnpackState.alignment);
    json->addScalar("RowLength", pixelUnpackState.rowLength);
    json->addScalar("SkipRows", pixelUnpackState.skipRows);
    json->addScalar("SkipPixels", pixelUnpackState.skipPixels);
    json->addScalar("ImageHeight", pixelUnpackState.imageHeight);
    json->addScalar("SkipImages", pixelUnpackState.skipImages);
}

void SerializeImageUnit(JsonSerializer *json, const gl::ImageUnit &imageUnit, int imageUnitIndex)
{
    GroupScope group(json, "ImageUnit", imageUnitIndex);
    json->addScalar("Level", imageUnit.level);
    json->addScalar("Layered", imageUnit.layered);
    json->addScalar("Layer", imageUnit.layer);
    json->addScalar("Access", imageUnit.access);
    json->addCString("Format", gl::GLinternalFormatToString(imageUnit.format));
    json->addScalar("TextureID", imageUnit.texture.id().value);
}

template <typename ResourceType>
void SerializeResourceID(JsonSerializer *json, const char *name, const ResourceType *resource)
{
    json->addScalar(name, resource ? resource->id().value : 0);
}

void SerializeContextState(JsonSerializer *json, const gl::State &state)
{
    GroupScope group(json, "ContextState");
    json->addScalar("Priority", state.getContextPriority());
    json->addScalar("Major", state.getClientVersion().getMajor());
    json->addScalar("Minor", state.getClientVersion().getMinor());
    SerializeColorFWithGroup(json, "ColorClearValue", state.getColorClearValue());
    json->addScalar("DepthClearValue", state.getDepthClearValue());
    json->addScalar("StencilClearValue", state.getStencilClearValue());
    SerializeRasterizerState(json, state.getRasterizerState());
    json->addScalar("ScissorTestEnabled", state.isScissorTestEnabled());
    SerializeRectangle(json, "Scissors", state.getScissor());
    SerializeBlendStateExt(json, state.getBlendStateExt());
    SerializeColorFWithGroup(json, "BlendColor", state.getBlendColor());
    json->addScalar("SampleAlphaToCoverageEnabled", state.isSampleAlphaToCoverageEnabled());
    json->addScalar("SampleCoverageEnabled", state.isSampleCoverageEnabled());
    json->addScalar("SampleCoverageValue", state.getSampleCoverageValue());
    json->addScalar("SampleCoverageInvert", state.getSampleCoverageInvert());
    json->addScalar("SampleMaskEnabled", state.isSampleMaskEnabled());
    json->addScalar("MaxSampleMaskWords", state.getMaxSampleMaskWords());
    {
        const auto &sampleMaskValues = state.getSampleMaskValues();
        GroupScope maskGroup(json, "SampleMaskValues");
        for (size_t i = 0; i < sampleMaskValues.size(); i++)
        {
            json->addScalar(ToString(i), sampleMaskValues[i]);
        }
    }
    SerializeDepthStencilState(json, state.getDepthStencilState());
    json->addScalar("StencilRef", state.getStencilRef());
    json->addScalar("StencilBackRef", state.getStencilBackRef());
    json->addScalar("LineWidth", state.getLineWidth());
    json->addScalar("GenerateMipmapHint", state.getGenerateMipmapHint());
    json->addScalar("FragmentShaderDerivativeHint", state.getFragmentShaderDerivativeHint());
    json->addScalar("BindGeneratesResourceEnabled", state.isBindGeneratesResourceEnabled());
    json->addScalar("ClientArraysEnabled", state.areClientArraysEnabled());
    SerializeRectangle(json, "Viewport", state.getViewport());
    json->addScalar("Near", state.getNearPlane());
    json->addScalar("Far", state.getFarPlane());
    json->addString("ClipOrigin", ToString(state.getClipOrigin()));
    json->addString("ClipDepthMode", ToString(state.getClipDepthMode()));
    SerializeResourceID(json, "ReadFramebufferID", state.getReadFramebuffer());
    SerializeResourceID(json, "DrawFramebufferID", state.getDrawFramebuffer());
    json->addScalar("RenderbufferID", state.getRenderbufferId().value);
    SerializeResourceID(json, "CurrentProgramID", state.getProgram());
    SerializeResourceID(json, "CurrentProgramPipelineID", state.getProgramPipeline());
    json->addString("ProvokingVertex", ToString(state.getProvokingVertex()));
    const std::vector<gl::VertexAttribCurrentValueData> &vertexAttribCurrentValues =
        state.getVertexAttribCurrentValues();
    for (size_t i = 0; i < vertexAttribCurrentValues.size(); i++)
    {
        GroupScope vagroup(json, "VertexAttribCurrentValue", static_cast<int>(i));
        SerializeVertexAttribCurrentValueData(json, vertexAttribCurrentValues[i]);
    }
    ASSERT(state.getVertexArray());
    json->addScalar("VertexArrayID", state.getVertexArray()->id().value);
    json->addScalar("CurrentValuesTypeMask", state.getCurrentValuesTypeMask().bits());
    json->addScalar("ActiveSampler", state.getActiveSampler());
    {
        GroupScope boundTexturesGroup(json, "BoundTextures");
        const gl::TextureBindingMap &boundTexturesMap = state.getBoundTexturesForCapture();
        for (gl::TextureType textureType : AllEnums<gl::TextureType>())
        {
            const gl::TextureBindingVector &textures = boundTexturesMap[textureType];
            GroupScope texturesGroup(json, ToString(textureType));
            SerializeBindingPointerVector<gl::Texture>(json, textures);
        }
    }

    std::vector<uint64_t> texturesIncompatibleWithSamplersVector;
    for (size_t index = 0; index < gl::ActiveTextureMask::ArraySize(); index++)
    {
        auto value = state.getTexturesIncompatibleWithSamplers().bits(index);
        texturesIncompatibleWithSamplersVector.push_back(value);
    }
    json->addVector("TexturesIncompatibleWithSamplers", texturesIncompatibleWithSamplersVector);

    {
        GroupScope texturesCacheGroup(json, "ActiveTexturesCache");

        const gl::ActiveTexturesCache &texturesCache = state.getActiveTexturesCache();
        for (GLuint textureIndex = 0; textureIndex < texturesCache.size(); ++textureIndex)
        {
            const gl::Texture *tex = texturesCache[textureIndex];
            std::stringstream strstr;
            strstr << "Tex " << std::setfill('0') << std::setw(2) << textureIndex;
            json->addScalar(strstr.str(), tex ? tex->id().value : 0);
        }
    }

    {
        GroupScope samplersGroupScope(json, "Samplers");
        SerializeBindingPointerVector<gl::Sampler>(json, state.getSamplers());
    }

    {
        GroupScope imageUnitsGroup(json, "BoundImageUnits");

        const std::vector<gl::ImageUnit> &imageUnits = state.getImageUnits();
        for (size_t imageUnitIndex = 0; imageUnitIndex < imageUnits.size(); ++imageUnitIndex)
        {
            const gl::ImageUnit &imageUnit = imageUnits[imageUnitIndex];
            SerializeImageUnit(json, imageUnit, static_cast<int>(imageUnitIndex));
        }
    }

    {
        const gl::ActiveQueryMap &activeQueries = state.getActiveQueriesForCapture();
        GroupScope activeQueriesGroup(json, "ActiveQueries");
        for (gl::QueryType queryType : AllEnums<gl::QueryType>())
        {
            const gl::BindingPointer<gl::Query> &query = activeQueries[queryType];
            std::stringstream strstr;
            strstr << queryType;
            json->addScalar(strstr.str(), query.id().value);
        }
    }

    {
        const gl::BoundBufferMap &boundBuffers = state.getBoundBuffersForCapture();
        GroupScope boundBuffersGroup(json, "BoundBuffers");
        for (gl::BufferBinding bufferBinding : AllEnums<gl::BufferBinding>())
        {
            const gl::BindingPointer<gl::Buffer> &buffer = boundBuffers[bufferBinding];
            std::stringstream strstr;
            strstr << bufferBinding;
            json->addScalar(strstr.str(), buffer.id().value);
        }
    }

    SerializeOffsetBindingPointerVector<gl::Buffer>(json, "UniformBufferBindings",
                                                    state.getOffsetBindingPointerUniformBuffers());
    SerializeOffsetBindingPointerVector<gl::Buffer>(
        json, "AtomicCounterBufferBindings", state.getOffsetBindingPointerAtomicCounterBuffers());
    SerializeOffsetBindingPointerVector<gl::Buffer>(
        json, "ShaderStorageBufferBindings", state.getOffsetBindingPointerShaderStorageBuffers());
    if (state.getCurrentTransformFeedback())
    {
        json->addScalar("CurrentTransformFeedback",
                        state.getCurrentTransformFeedback()->id().value);
    }
    SerializePixelUnpackState(json, state.getUnpackState());
    SerializePixelPackState(json, state.getPackState());
    json->addScalar("PrimitiveRestartEnabled", state.isPrimitiveRestartEnabled());
    json->addScalar("MultisamplingEnabled", state.isMultisamplingEnabled());
    json->addScalar("SampleAlphaToOneEnabled", state.isSampleAlphaToOneEnabled());
    json->addScalar("FramebufferSRGB", state.getFramebufferSRGB());
    json->addScalar("RobustResourceInitEnabled", state.isRobustResourceInitEnabled());
    json->addScalar("ProgramBinaryCacheEnabled", state.isProgramBinaryCacheEnabled());
    json->addScalar("TextureRectangleEnabled", state.isTextureRectangleEnabled());
    json->addScalar("MaxShaderCompilerThreads", state.getMaxShaderCompilerThreads());
    json->addScalar("EnabledClipDistances", state.getEnabledClipDistances().bits());
    json->addScalar("BlendFuncConstantAlphaDrawBuffers",
                    state.getBlendFuncConstantAlphaDrawBuffers().bits());
    json->addScalar("BlendFuncConstantColorDrawBuffers",
                    state.getBlendFuncConstantColorDrawBuffers().bits());
    json->addScalar("SimultaneousConstantColorAndAlphaBlendFunc",
                    state.noSimultaneousConstantColorAndAlphaBlendFunc());
}

void SerializeBufferState(JsonSerializer *json, const gl::BufferState &bufferState)
{
    json->addString("Label", bufferState.getLabel());
    json->addString("Usage", ToString(bufferState.getUsage()));
    json->addScalar("Size", bufferState.getSize());
    json->addScalar("AccessFlags", bufferState.getAccessFlags());
    json->addScalar("Access", bufferState.getAccess());
    json->addScalar("Mapped", bufferState.isMapped());
    json->addScalar("MapOffset", bufferState.getMapOffset());
    json->addScalar("MapLength", bufferState.getMapLength());
}

Result SerializeBuffer(const gl::Context *context,
                       JsonSerializer *json,
                       ScratchBuffer *scratchBuffer,
                       gl::Buffer *buffer)
{
    GroupScope group(json, "Buffer", buffer->id().value);
    SerializeBufferState(json, buffer->getState());
    if (buffer->getSize() > 0)
    {
        MemoryBuffer *dataPtr = nullptr;
        ANGLE_CHECK_GL_ALLOC(
            const_cast<gl::Context *>(context),
            scratchBuffer->getInitialized(static_cast<size_t>(buffer->getSize()), &dataPtr, 0));
        ANGLE_TRY(buffer->getSubData(context, 0, dataPtr->size(), dataPtr->data()));
        json->addBlob("data", *dataPtr);
    }
    else
    {
        json->addCString("data", "null");
    }
    return Result::Continue;
}

void SerializeColorGeneric(JsonSerializer *json,
                           const std::string &name,
                           const ColorGeneric &colorGeneric)
{
    GroupScope group(json, name);
    ASSERT(colorGeneric.type == ColorGeneric::Type::Float ||
           colorGeneric.type == ColorGeneric::Type::Int ||
           colorGeneric.type == ColorGeneric::Type::UInt);
    json->addCString("Type", ColorGenericTypeToString(colorGeneric.type));
    if (colorGeneric.type == ColorGeneric::Type::Float)
    {
        SerializeColorF(json, colorGeneric.colorF);
    }
    else if (colorGeneric.type == ColorGeneric::Type::Int)
    {
        SerializeColorI(json, colorGeneric.colorI);
    }
    else
    {
        SerializeColorUI(json, colorGeneric.colorUI);
    }
}

void SerializeSamplerState(JsonSerializer *json, const gl::SamplerState &samplerState)
{
    json->addScalar("MinFilter", samplerState.getMinFilter());
    json->addScalar("MagFilter", samplerState.getMagFilter());
    json->addScalar("WrapS", samplerState.getWrapS());
    json->addScalar("WrapT", samplerState.getWrapT());
    json->addScalar("WrapR", samplerState.getWrapR());
    json->addScalar("MaxAnisotropy", samplerState.getMaxAnisotropy());
    json->addScalar("MinLod", samplerState.getMinLod());
    json->addScalar("MaxLod", samplerState.getMaxLod());
    json->addScalar("CompareMode", samplerState.getCompareMode());
    json->addScalar("CompareFunc", samplerState.getCompareFunc());
    json->addScalar("SRGBDecode", samplerState.getSRGBDecode());
    SerializeColorGeneric(json, "BorderColor", samplerState.getBorderColor());
}

void SerializeSampler(JsonSerializer *json, gl::Sampler *sampler)
{
    GroupScope group(json, "Sampler", sampler->id().value);
    json->addString("Label", sampler->getLabel());
    SerializeSamplerState(json, sampler->getSamplerState());
}

void SerializeSwizzleState(JsonSerializer *json, const gl::SwizzleState &swizzleState)
{
    json->addScalar("SwizzleRed", swizzleState.swizzleRed);
    json->addScalar("SwizzleGreen", swizzleState.swizzleGreen);
    json->addScalar("SwizzleBlue", swizzleState.swizzleBlue);
    json->addScalar("SwizzleAlpha", swizzleState.swizzleAlpha);
}

void SerializeRenderbufferState(JsonSerializer *json,
                                const gl::RenderbufferState &renderbufferState)
{
    GroupScope wg(json, "State");
    json->addScalar("Width", renderbufferState.getWidth());
    json->addScalar("Height", renderbufferState.getHeight());
    SerializeGLFormat(json, renderbufferState.getFormat());
    json->addScalar("Samples", renderbufferState.getSamples());
    json->addCString("InitState", InitStateToString(renderbufferState.getInitState()));
}

Result SerializeRenderbuffer(const gl::Context *context,
                             JsonSerializer *json,
                             ScratchBuffer *scratchBuffer,
                             gl::Renderbuffer *renderbuffer)
{
    GroupScope wg(json, "Renderbuffer", renderbuffer->id().value);
    SerializeRenderbufferState(json, renderbuffer->getState());
    json->addString("Label", renderbuffer->getLabel());

    if (renderbuffer->initState(GL_NONE, gl::ImageIndex()) == gl::InitState::Initialized)
    {
        if (renderbuffer->getSamples() > 1 && renderbuffer->getFormat().info->depthBits > 0)
        {
            // Vulkan can't do resolve blits for multisampled depth attachemnts and
            // we don't implement an emulation, therefore we can't read back any useful
            // data here.
            json->addCString("Pixels", "multisampled depth buffer");
        }
        else if (renderbuffer->getWidth() * renderbuffer->getHeight() <= 0)
        {
            json->addCString("Pixels", "no pixels");
        }
        else
        {
            const gl::InternalFormat &format = *renderbuffer->getFormat().info;

            const gl::Extents size(renderbuffer->getWidth(), renderbuffer->getHeight(), 1);
            gl::PixelPackState packState;
            packState.alignment = 1;

            GLenum readFormat = renderbuffer->getImplementationColorReadFormat(context);
            GLenum readType   = renderbuffer->getImplementationColorReadType(context);

            GLuint bytes = 0;
            bool computeOK =
                format.computePackUnpackEndByte(readType, size, packState, false, &bytes);
            ASSERT(computeOK);

            MemoryBuffer *pixelsPtr = nullptr;
            ANGLE_CHECK_GL_ALLOC(const_cast<gl::Context *>(context),
                                 scratchBuffer->getInitialized(bytes, &pixelsPtr, 0));

            ANGLE_TRY(renderbuffer->getImplementation()->getRenderbufferImage(
                context, packState, nullptr, readFormat, readType, pixelsPtr->data()));
            json->addBlob("Pixels", *pixelsPtr);
        }
    }
    else
    {
        json->addCString("Pixels", "Not initialized");
    }
    return Result::Continue;
}

void SerializeWorkGroupSize(JsonSerializer *json, const sh::WorkGroupSize &workGroupSize)
{
    GroupScope wg(json, "workGroupSize");
    json->addScalar("x", workGroupSize[0]);
    json->addScalar("y", workGroupSize[1]);
    json->addScalar("z", workGroupSize[2]);
}

void SerializeUniformIndexToBufferBinding(JsonSerializer *json,
                                          const gl::ProgramUniformBlockArray<GLuint> &blockToBuffer)
{
    GroupScope wg(json, "uniformBlockIndexToBufferBinding");
    for (size_t blockIndex = 0; blockIndex < blockToBuffer.size(); ++blockIndex)
    {
        json->addScalar(ToString(blockIndex), blockToBuffer[blockIndex]);
    }
}

void SerializeShaderVariable(JsonSerializer *json, const sh::ShaderVariable &shaderVariable)
{
    GroupScope wg(json, "ShaderVariable");
    json->addScalar("Type", shaderVariable.type);
    json->addScalar("Precision", shaderVariable.precision);
    json->addString("Name", shaderVariable.name);
    json->addString("MappedName", shaderVariable.mappedName);
    json->addVector("ArraySizes", shaderVariable.arraySizes);
    json->addScalar("StaticUse", shaderVariable.staticUse);
    json->addScalar("Active", shaderVariable.active);
    for (const sh::ShaderVariable &field : shaderVariable.fields)
    {
        SerializeShaderVariable(json, field);
    }
    json->addString("StructOrBlockName", shaderVariable.structOrBlockName);
    json->addString("MappedStructOrBlockName", shaderVariable.mappedStructOrBlockName);
    json->addScalar("RowMajorLayout", shaderVariable.isRowMajorLayout);
    json->addScalar("Location", shaderVariable.location);
    json->addScalar("Binding", shaderVariable.binding);
    json->addScalar("ImageUnitFormat", shaderVariable.imageUnitFormat);
    json->addScalar("Offset", shaderVariable.offset);
    json->addScalar("Readonly", shaderVariable.readonly);
    json->addScalar("Writeonly", shaderVariable.writeonly);
    json->addScalar("Index", shaderVariable.index);
    json->addScalar("YUV", shaderVariable.yuv);
    json->addCString("Interpolation", InterpolationTypeToString(shaderVariable.interpolation));
    json->addScalar("Invariant", shaderVariable.isInvariant);
    json->addScalar("TexelFetchStaticUse", shaderVariable.texelFetchStaticUse);
}

void SerializeShaderVariablesVector(JsonSerializer *json,
                                    const std::vector<sh::ShaderVariable> &shaderVariables)
{
    for (const sh::ShaderVariable &shaderVariable : shaderVariables)
    {
        SerializeShaderVariable(json, shaderVariable);
    }
}

void SerializeInterfaceBlocksVector(JsonSerializer *json,
                                    const std::vector<sh::InterfaceBlock> &interfaceBlocks)
{
    for (const sh::InterfaceBlock &interfaceBlock : interfaceBlocks)
    {
        GroupScope group(json, "Interface Block");
        json->addString("Name", interfaceBlock.name);
        json->addString("MappedName", interfaceBlock.mappedName);
        json->addString("InstanceName", interfaceBlock.instanceName);
        json->addScalar("ArraySize", interfaceBlock.arraySize);
        json->addCString("Layout", BlockLayoutTypeToString(interfaceBlock.layout));
        json->addScalar("Binding", interfaceBlock.binding);
        json->addScalar("StaticUse", interfaceBlock.staticUse);
        json->addScalar("Active", interfaceBlock.active);
        json->addCString("BlockType", BlockTypeToString(interfaceBlock.blockType));
        SerializeShaderVariablesVector(json, interfaceBlock.fields);
    }
}

void SerializeCompiledShaderState(JsonSerializer *json, const gl::SharedCompiledShaderState &state)
{
    json->addCString("Type", gl::ShaderTypeToString(state->shaderType));
    json->addScalar("Version", state->shaderVersion);
    json->addString("TranslatedSource", *state->translatedSource);
    json->addVectorAsHash("CompiledBinary", state->compiledBinary);
    SerializeWorkGroupSize(json, state->localSize);
    SerializeShaderVariablesVector(json, state->inputVaryings);
    SerializeShaderVariablesVector(json, state->outputVaryings);
    SerializeShaderVariablesVector(json, state->uniforms);
    SerializeInterfaceBlocksVector(json, state->uniformBlocks);
    SerializeInterfaceBlocksVector(json, state->shaderStorageBlocks);
    SerializeShaderVariablesVector(json, state->allAttributes);
    SerializeShaderVariablesVector(json, state->activeAttributes);
    SerializeShaderVariablesVector(json, state->activeOutputVariables);
    json->addScalar("NumViews", state->numViews);
    json->addScalar("MetadataFlags", state->metadataFlags.bits());
    json->addScalar("AdvancedBlendEquations", state->advancedBlendEquations.bits());
    json->addString("GeometryShaderInputPrimitiveType",
                    ToString(state->geometryShaderInputPrimitiveType));
    json->addString("GeometryShaderOutputPrimitiveType",
                    ToString(state->geometryShaderOutputPrimitiveType));
    json->addScalar("GeometryShaderMaxVertices", state->geometryShaderMaxVertices);
    json->addScalar("GeometryShaderInvocations", state->geometryShaderInvocations);
    json->addScalar("TessControlShaderVertices", state->tessControlShaderVertices);
    json->addScalar("TessGenMode", state->tessGenMode);
    json->addScalar("TessGenSpacing", state->tessGenSpacing);
    json->addScalar("TessGenVertexOrder", state->tessGenVertexOrder);
    json->addScalar("TessGenPointMode", state->tessGenPointMode);
}

void SerializeShaderState(JsonSerializer *json, const gl::ShaderState &shaderState)
{
    GroupScope group(json, "ShaderState");
    json->addString("Label", shaderState.getLabel());
    json->addString("Source", shaderState.getSource());
    json->addCString("CompileStatus", CompileStatusToString(shaderState.getCompileStatus()));
}

void SerializeShader(const gl::Context *context,
                     JsonSerializer *json,
                     GLuint id,
                     gl::Shader *shader)
{
    // Ensure deterministic compilation.
    shader->resolveCompile(context);

    GroupScope group(json, "Shader", id);
    SerializeShaderState(json, shader->getState());
    SerializeCompiledShaderState(json, shader->getCompiledState());
    json->addScalar("Handle", shader->getHandle().value);
    // TODO: implement MEC context validation only after all contexts have been initialized
    // http://anglebug.com/42266488
    // json->addScalar("RefCount", shader->getRefCount());
    json->addScalar("FlaggedForDeletion", shader->isFlaggedForDeletion());
    // Do not serialize mType because it is already serialized in SerializeCompiledShaderState.
    json->addString("InfoLogString", shader->getInfoLogString());
    // Do not serialize compiler resources string because it can vary between test modes.
}

void SerializeVariableLocationsVector(JsonSerializer *json,
                                      const std::string &group_name,
                                      const std::vector<gl::VariableLocation> &variableLocations)
{
    GroupScope group(json, group_name);
    for (size_t locIndex = 0; locIndex < variableLocations.size(); ++locIndex)
    {
        const gl::VariableLocation &variableLocation = variableLocations[locIndex];
        GroupScope vargroup(json, "Location", static_cast<int>(locIndex));
        json->addScalar("ArrayIndex", variableLocation.arrayIndex);
        json->addScalar("Index", variableLocation.index);
        json->addScalar("Ignored", variableLocation.ignored);
    }
}

void SerializeBlockMemberInfo(JsonSerializer *json, const sh::BlockMemberInfo &blockMemberInfo)
{
    GroupScope group(json, "BlockMemberInfo");
    json->addScalar("Offset", blockMemberInfo.offset);
    json->addScalar("Stride", blockMemberInfo.arrayStride);
    json->addScalar("MatrixStride", blockMemberInfo.matrixStride);
    json->addScalar("IsRowMajorMatrix", blockMemberInfo.isRowMajorMatrix);
    json->addScalar("TopLevelArrayStride", blockMemberInfo.topLevelArrayStride);
}

void SerializeBufferVariablesVector(JsonSerializer *json,
                                    const std::vector<gl::BufferVariable> &bufferVariables)
{
    for (const gl::BufferVariable &bufferVariable : bufferVariables)
    {
        GroupScope group(json, "BufferVariable");
        json->addString("Name", bufferVariable.name);
        json->addString("MappedName", bufferVariable.mappedName);

        json->addScalar("Type", bufferVariable.pod.type);
        json->addScalar("Precision", bufferVariable.pod.precision);
        json->addScalar("activeUseBits", bufferVariable.activeShaders().bits());
        for (const gl::ShaderType shaderType : gl::AllShaderTypes())
        {
            json->addScalar(
                gl::ShaderTypeToString(shaderType),
                bufferVariable.isActive(shaderType) ? bufferVariable.getId(shaderType) : 0);
        }

        json->addScalar("BufferIndex", bufferVariable.pod.bufferIndex);
        SerializeBlockMemberInfo(json, bufferVariable.pod.blockInfo);

        json->addScalar("TopLevelArraySize", bufferVariable.pod.topLevelArraySize);
        json->addScalar("basicTypeElementCount", bufferVariable.pod.basicTypeElementCount);
        json->addScalar("isArray", bufferVariable.pod.isArray);
    }
}

void SerializeProgramAliasedBindings(JsonSerializer *json,
                                     const gl::ProgramAliasedBindings &programAliasedBindings)
{
    for (const auto &programAliasedBinding : programAliasedBindings)
    {
        GroupScope group(json, programAliasedBinding.first);
        json->addScalar("Location", programAliasedBinding.second.location);
        json->addScalar("Aliased", programAliasedBinding.second.aliased);
    }
}

void SerializeProgramState(JsonSerializer *json, const gl::ProgramState &programState)
{
    json->addString("Label", programState.getLabel());
    json->addVectorOfStrings("TransformFeedbackVaryingNames",
                             programState.getTransformFeedbackVaryingNames());
    json->addScalar("BinaryRetrieveableHint", programState.hasBinaryRetrieveableHint());
    json->addScalar("Separable", programState.isSeparable());
    SerializeProgramAliasedBindings(json, programState.getUniformLocationBindings());

    const gl::ProgramExecutable &executable = programState.getExecutable();

    SerializeWorkGroupSize(json, executable.getComputeShaderLocalSize());
    SerializeUniformIndexToBufferBinding(
        json, executable.getUniformBlockIndexToBufferBindingForCapture());
    SerializeVariableLocationsVector(json, "UniformLocations", executable.getUniformLocations());
    SerializeBufferVariablesVector(json, executable.getBufferVariables());
    SerializeRange(json, executable.getAtomicCounterUniformRange());
    SerializeVariableLocationsVector(json, "SecondaryOutputLocations",
                                     executable.getSecondaryOutputLocations());
    json->addScalar("NumViews", executable.getNumViews());
    json->addScalar("DrawIDLocation", executable.getDrawIDLocation());
    json->addScalar("BaseVertexLocation", executable.getBaseVertexLocation());
    json->addScalar("BaseInstanceLocation", executable.getBaseInstanceLocation());
}

void SerializeProgramBindings(JsonSerializer *json, const gl::ProgramBindings &programBindings)
{
    for (const auto &programBinding : programBindings)
    {
        json->addScalar(programBinding.first, programBinding.second);
    }
}

template <typename T>
void SerializeUniformData(JsonSerializer *json,
                          const gl::Context *context,
                          const gl::ProgramExecutable &executable,
                          gl::UniformLocation loc,
                          GLenum type,
                          GLint size,
                          void (gl::ProgramExecutable::*getFunc)(const gl::Context *,
                                                                 gl::UniformLocation,
                                                                 T *) const)
{
    std::vector<T> uniformData(gl::VariableComponentCount(type) * size, 0);
    (executable.*getFunc)(context, loc, uniformData.data());
    json->addVector("Data", uniformData);
}

void SerializeProgram(JsonSerializer *json,
                      const gl::Context *context,
                      GLuint id,
                      gl::Program *program)
{
    // Ensure deterministic link.
    program->resolveLink(context);

    GroupScope group(json, "Program", id);

    std::vector<GLint> shaderHandles;
    for (gl::ShaderType shaderType : gl::AllShaderTypes())
    {
        gl::Shader *shader = program->getAttachedShader(shaderType);
        shaderHandles.push_back(shader ? shader->getHandle().value : 0);
    }
    json->addVector("Handle", shaderHandles);

    SerializeProgramState(json, program->getState());
    json->addScalar("IsValidated", program->isValidated());
    SerializeProgramBindings(json, program->getAttributeBindings());
    SerializeProgramAliasedBindings(json, program->getFragmentOutputLocations());
    SerializeProgramAliasedBindings(json, program->getFragmentOutputIndexes());
    json->addScalar("IsLinked", program->isLinked());
    json->addScalar("IsFlaggedForDeletion", program->isFlaggedForDeletion());
    // TODO: implement MEC context validation only after all contexts have been initialized
    // http://anglebug.com/42266488
    // json->addScalar("RefCount", program->getRefCount());
    json->addScalar("ID", program->id().value);

    const gl::ProgramExecutable &executable = program->getExecutable();

    // Serialize uniforms.
    {
        GroupScope uniformsGroup(json, "Uniforms");
        GLint uniformCount = static_cast<GLint>(executable.getUniforms().size());
        for (int uniformIndex = 0; uniformIndex < uniformCount; ++uniformIndex)
        {
            GroupScope uniformGroup(json, "Uniform", uniformIndex);

            constexpr GLsizei kMaxUniformNameLen = 1024;
            char uniformName[kMaxUniformNameLen] = {};
            GLint size                           = 0;
            GLenum type                          = GL_NONE;
            executable.getActiveUniform(uniformIndex, kMaxUniformNameLen, nullptr, &size, &type,
                                        uniformName);

            json->addCString("Name", uniformName);
            json->addScalar("Size", size);
            json->addCString("Type", gl::GLenumToString(gl::GLESEnum::AttributeType, type));

            const gl::UniformLocation loc = executable.getUniformLocation(uniformName);

            if (loc.value == -1)
            {
                continue;
            }

            switch (gl::VariableComponentType(type))
            {
                case GL_FLOAT:
                {
                    SerializeUniformData<GLfloat>(json, context, executable, loc, type, size,
                                                  &gl::ProgramExecutable::getUniformfv);
                    break;
                }
                case GL_BOOL:
                case GL_INT:
                {
                    SerializeUniformData<GLint>(json, context, executable, loc, type, size,
                                                &gl::ProgramExecutable::getUniformiv);
                    break;
                }
                case GL_UNSIGNED_INT:
                {
                    SerializeUniformData<GLuint>(json, context, executable, loc, type, size,
                                                 &gl::ProgramExecutable::getUniformuiv);
                    break;
                }
                default:
                    UNREACHABLE();
                    break;
            }
        }
    }
}

void SerializeImageDesc(JsonSerializer *json, size_t descIndex, const gl::ImageDesc &imageDesc)
{
    // Skip serializing unspecified image levels.
    if (imageDesc.size.empty())
    {
        return;
    }

    GroupScope group(json, "ImageDesc", static_cast<int>(descIndex));
    SerializeExtents(json, imageDesc.size);
    SerializeGLFormat(json, imageDesc.format);
    json->addScalar("Samples", imageDesc.samples);
    json->addScalar("FixesSampleLocations", imageDesc.fixedSampleLocations);
    json->addCString("InitState", InitStateToString(imageDesc.initState));
}

void SerializeTextureState(JsonSerializer *json, const gl::TextureState &textureState)
{
    json->addString("Type", ToString(textureState.getType()));
    SerializeSwizzleState(json, textureState.getSwizzleState());
    {
        GroupScope samplerStateGroup(json, "SamplerState");
        SerializeSamplerState(json, textureState.getSamplerState());
    }
    json->addCString("SRGB", SrgbOverrideToString(textureState.getSRGBOverride()));
    json->addScalar("BaseLevel", textureState.getBaseLevel());
    json->addScalar("MaxLevel", textureState.getMaxLevel());
    json->addScalar("DepthStencilTextureMode", textureState.getDepthStencilTextureMode());
    json->addScalar("BeenBoundAsImage", textureState.hasBeenBoundAsImage());
    json->addScalar("ImmutableFormat", textureState.getImmutableFormat());
    json->addScalar("ImmutableLevels", textureState.getImmutableLevels());
    json->addScalar("Usage", textureState.getUsage());
    SerializeRectangle(json, "Crop", textureState.getCrop());
    json->addScalar("GenerateMipmapHint", textureState.getGenerateMipmapHint());
    json->addCString("InitState", InitStateToString(textureState.getInitState()));
    json->addScalar("BoundBufferID", textureState.getBuffer().id().value);

    {
        GroupScope descGroup(json, "ImageDescs");
        const std::vector<gl::ImageDesc> &imageDescs = textureState.getImageDescs();
        for (size_t descIndex = 0; descIndex < imageDescs.size(); ++descIndex)
        {
            SerializeImageDesc(json, descIndex, imageDescs[descIndex]);
        }
    }
}

Result SerializeTextureData(JsonSerializer *json,
                            const gl::Context *context,
                            gl::Texture *texture,
                            ScratchBuffer *scratchBuffer)
{
    gl::ImageIndexIterator imageIter = gl::ImageIndexIterator::MakeGeneric(
        texture->getType(), texture->getBaseLevel(), texture->getMipmapMaxLevel() + 1,
        gl::ImageIndex::kEntireLevel, gl::ImageIndex::kEntireLevel);
    while (imageIter.hasNext())
    {
        gl::ImageIndex index = imageIter.next();

        // Skip serializing level data if the level index is out of range
        GLuint levelIndex = index.getLevelIndex();
        if (levelIndex > texture->getMipmapMaxLevel() || levelIndex < texture->getBaseLevel())
            continue;

        const gl::ImageDesc &desc = texture->getTextureState().getImageDesc(index);

        if (desc.size.empty())
            continue;

        const gl::InternalFormat &format = *desc.format.info;

        // Check for supported textures
        ASSERT(index.getType() == gl::TextureType::_2D || index.getType() == gl::TextureType::_3D ||
               index.getType() == gl::TextureType::_2DArray ||
               index.getType() == gl::TextureType::CubeMap ||
               index.getType() == gl::TextureType::CubeMapArray ||
               index.getType() == gl::TextureType::_2DMultisampleArray ||
               index.getType() == gl::TextureType::_2DMultisample ||
               index.getType() == gl::TextureType::External);

        GLenum glFormat = format.format;
        GLenum glType   = format.type;

        const gl::Extents size(desc.size.width, desc.size.height, desc.size.depth);
        gl::PixelPackState packState;
        packState.alignment = 1;

        GLuint endByte  = 0;
        bool unpackSize = format.computePackUnpackEndByte(glType, size, packState, true, &endByte);
        ASSERT(unpackSize);
        MemoryBuffer *texelsPtr = nullptr;
        ANGLE_CHECK_GL_ALLOC(const_cast<gl::Context *>(context),
                             scratchBuffer->getInitialized(endByte, &texelsPtr, 0));

        std::stringstream label;

        label << "Texels-Level" << index.getLevelIndex();
        if (imageIter.current().hasLayer())
        {
            label << "-Layer" << imageIter.current().getLayerIndex();
        }

        if (texture->getState().getInitState() == gl::InitState::Initialized)
        {
            if (format.compressed)
            {
                // TODO: Read back compressed data. http://anglebug.com/42264702
                json->addCString(label.str(), "compressed texel data");
            }
            else
            {
                ANGLE_TRY(texture->getTexImage(context, packState, nullptr, index.getTarget(),
                                               index.getLevelIndex(), glFormat, glType,
                                               texelsPtr->data()));
                json->addBlob(label.str(), *texelsPtr);
            }
        }
        else
        {
            json->addCString(label.str(), "not initialized");
        }
    }
    return Result::Continue;
}

Result SerializeTexture(const gl::Context *context,
                        JsonSerializer *json,
                        ScratchBuffer *scratchBuffer,
                        gl::Texture *texture)
{
    GroupScope group(json, "Texture", texture->getId());

    // We serialize texture data first, to force the texture state to be initialized.
    if (texture->getType() != gl::TextureType::Buffer)
    {
        ANGLE_TRY(SerializeTextureData(json, context, texture, scratchBuffer));
    }

    SerializeTextureState(json, texture->getState());
    json->addString("Label", texture->getLabel());
    // FrameCapture can not serialize mBoundSurface and mBoundStream
    // because they are likely to change with each run
    return Result::Continue;
}

void SerializeVertexAttributeVector(JsonSerializer *json,
                                    const std::vector<gl::VertexAttribute> &vertexAttributes)
{
    for (size_t attribIndex = 0; attribIndex < vertexAttributes.size(); ++attribIndex)
    {
        GroupScope group(json, "VertexAttribute", static_cast<int>(attribIndex));
        const gl::VertexAttribute &vertexAttribute = vertexAttributes[attribIndex];
        json->addScalar("BindingIndex", vertexAttribute.bindingIndex);
        json->addScalar("Enabled", vertexAttribute.enabled);
        ASSERT(vertexAttribute.format);
        SerializeANGLEFormat(json, vertexAttribute.format);
        json->addScalar("RelativeOffset", vertexAttribute.relativeOffset);
        json->addScalar("VertexAttribArrayStride", vertexAttribute.vertexAttribArrayStride);
    }
}

void SerializeVertexBindingsVector(JsonSerializer *json,
                                   const std::vector<gl::VertexBinding> &vertexBindings,
                                   const gl::VertexArrayBuffers &vertexBuffers)
{
    ASSERT(vertexBindings.size() <= gl::kElementArrayBufferIndex);
    gl::Buffer *elementBuffer = vertexBuffers[gl::kElementArrayBufferIndex].get();
    if (elementBuffer)
    {
        json->addScalar("ElementArrayBufferID", elementBuffer->id().value);
    }
    else
    {
        json->addScalar("ElementArrayBufferID", 0);
    }

    for (size_t bindingIndex = 0; bindingIndex < vertexBindings.size(); ++bindingIndex)
    {
        GroupScope group(json, "VertexBinding", static_cast<int>(bindingIndex));
        const gl::VertexBinding &vertexBinding = vertexBindings[bindingIndex];
        json->addScalar("Stride", vertexBinding.getStride());
        json->addScalar("Divisor", vertexBinding.getDivisor());
        json->addScalar("Offset", vertexBinding.getOffset());
        json->addScalar("BufferID", vertexBuffers[bindingIndex].id().value);
        json->addScalar("BoundAttributesMask", vertexBinding.getBoundAttributesMask().bits());
    }
}

void SerializeVertexArrayState(JsonSerializer *json, const gl::VertexArrayState &vertexArrayState)
{
    json->addString("Label", vertexArrayState.getLabel());
    SerializeVertexAttributeVector(json, vertexArrayState.getVertexAttributes());
    json->addScalar("EnabledAttributesMask", vertexArrayState.getEnabledAttributesMask().bits());
    json->addScalar("VertexAttributesTypeMask",
                    vertexArrayState.getVertexAttributesTypeMask().bits());
    json->addScalar("ClientMemoryAttribsMask",
                    vertexArrayState.getClientMemoryAttribsMask().bits());
    json->addScalar("NullPointerClientMemoryAttribsMask",
                    vertexArrayState.getNullPointerClientMemoryAttribsMask().bits());
}

void SerializeVertexArray(JsonSerializer *json, gl::VertexArray *vertexArray)
{
    GroupScope group(json, "VertexArray", vertexArray->id().value);
    SerializeVertexArrayState(json, vertexArray->getState());
    SerializeVertexBindingsVector(json, vertexArray->getVertexBindings(),
                                  vertexArray->getBufferBindingPointers());
}

}  // namespace

Result SerializeContextToString(const gl::Context *context, std::string *stringOut)
{
    JsonSerializer json;
    json.startGroup("Context");

    SerializeContextState(&json, context->getState());
    ScratchBuffer scratchBuffer(1);
    {
        const gl::FramebufferManager &framebufferManager =
            context->getState().getFramebufferManagerForCapture();
        GroupScope framebufferGroup(&json, "FramebufferManager");
        for (const auto &framebuffer :
             gl::UnsafeResourceMapIter(framebufferManager.getResourcesForCapture()))
        {
            gl::Framebuffer *framebufferPtr = framebuffer.second;
            ANGLE_TRY(SerializeFramebuffer(context, &json, &scratchBuffer, framebufferPtr));
        }
    }
    {
        const gl::BufferManager &bufferManager = context->getState().getBufferManagerForCapture();
        GroupScope framebufferGroup(&json, "BufferManager");
        for (const auto &buffer : gl::UnsafeResourceMapIter(bufferManager.getResourcesForCapture()))
        {
            gl::Buffer *bufferPtr = buffer.second;
            ANGLE_TRY(SerializeBuffer(context, &json, &scratchBuffer, bufferPtr));
        }
    }
    {
        const gl::SamplerManager &samplerManager =
            context->getState().getSamplerManagerForCapture();
        GroupScope samplerGroup(&json, "SamplerManager");
        for (const auto &sampler :
             gl::UnsafeResourceMapIter(samplerManager.getResourcesForCapture()))
        {
            gl::Sampler *samplerPtr = sampler.second;
            SerializeSampler(&json, samplerPtr);
        }
    }
    {
        const gl::RenderbufferManager &renderbufferManager =
            context->getState().getRenderbufferManagerForCapture();
        GroupScope renderbufferGroup(&json, "RenderbufferManager");
        for (const auto &renderbuffer :
             gl::UnsafeResourceMapIter(renderbufferManager.getResourcesForCapture()))
        {
            gl::Renderbuffer *renderbufferPtr = renderbuffer.second;
            ANGLE_TRY(SerializeRenderbuffer(context, &json, &scratchBuffer, renderbufferPtr));
        }
    }
    const gl::ShaderProgramManager &shaderProgramManager =
        context->getState().getShaderProgramManagerForCapture();
    {
        const gl::ResourceMap<gl::Shader, gl::ShaderProgramID> &shaderManager =
            shaderProgramManager.getShadersForCapture();
        GroupScope shaderGroup(&json, "ShaderManager");
        for (const auto &shader : gl::UnsafeResourceMapIter(shaderManager))
        {
            GLuint id             = shader.first;
            gl::Shader *shaderPtr = shader.second;
            SerializeShader(context, &json, id, shaderPtr);
        }
    }
    {
        const gl::ResourceMap<gl::Program, gl::ShaderProgramID> &programManager =
            shaderProgramManager.getProgramsForCaptureAndPerf();
        GroupScope shaderGroup(&json, "ProgramManager");
        for (const auto &program : gl::UnsafeResourceMapIter(programManager))
        {
            GLuint id               = program.first;
            gl::Program *programPtr = program.second;
            SerializeProgram(&json, context, id, programPtr);
        }
    }
    {
        const gl::TextureManager &textureManager =
            context->getState().getTextureManagerForCapture();
        GroupScope shaderGroup(&json, "TextureManager");
        for (const auto &texture :
             gl::UnsafeResourceMapIter(textureManager.getResourcesForCapture()))
        {
            gl::Texture *texturePtr = texture.second;
            ANGLE_TRY(SerializeTexture(context, &json, &scratchBuffer, texturePtr));
        }
    }
    {
        const gl::VertexArrayMap &vertexArrayMap = context->getVertexArraysForCapture();
        GroupScope shaderGroup(&json, "VertexArrayMap");
        for (const auto &vertexArray : gl::UnsafeResourceMapIter(vertexArrayMap))
        {
            gl::VertexArray *vertexArrayPtr = vertexArray.second;
            SerializeVertexArray(&json, vertexArrayPtr);
        }
    }
    json.endGroup();

    *stringOut = json.data();

    scratchBuffer.clear();
    return Result::Continue;
}

}  // namespace angle
