Edit

kc3-lang/angle/src/libANGLE/frame_capture_utils.cpp

Branch :

  • Show log

    Commit

  • Author : Manh Nguyen
    Date : 2020-07-23 11:12:46
    Hash : db88baa8
    Message : Serializes GL context states and reformats frame_capture_utils Adds the ability to serialize GL context states. Adds serialization of GL context states to serializeContext method so that capture replay regression testing now compares the GL context states. Reformats frame_capture_utils to make most serialization methods private, except for the ones called by other classes and template methods. Bug: angleproject:4817 Change-Id: I2d53c88be3d503268bd6e2e5058b5fabe0644f67 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2314829 Commit-Queue: Manh Nguyen <nguyenmh@google.com> Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Cody Northrop <cnorthrop@google.com>

  • src/libANGLE/frame_capture_utils.cpp
  • //
    // 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.
    //
    // frame_capture_utils.cpp:
    //   ANGLE frame capture util implementation.
    //
    
    #include "libANGLE/frame_capture_utils.h"
    
    #include <vector>
    
    #include "common/Color.h"
    #include "common/MemoryBuffer.h"
    #include "common/angleutils.h"
    #include "libANGLE/BinaryStream.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/State.h"
    #include "libANGLE/TransformFeedback.h"
    #include "libANGLE/VertexAttribute.h"
    #include "libANGLE/angletypes.h"
    #include "libANGLE/renderer/FramebufferImpl.h"
    
    namespace angle
    {
    
    namespace
    {
    
    template <typename T>
    void SerializeColor(gl::BinaryOutputStream *bos, const Color<T> &color)
    {
        bos->writeInt(color.red);
        bos->writeInt(color.green);
        bos->writeInt(color.blue);
        bos->writeInt(color.alpha);
    }
    
    template void SerializeColor<float>(gl::BinaryOutputStream *bos, const Color<float> &color);
    
    template <class ObjectType>
    void SerializeOffsetBindingPointerVector(
        gl::BinaryOutputStream *bos,
        const std::vector<gl::OffsetBindingPointer<ObjectType>> &offsetBindingPointerVector)
    {
        for (size_t i = 0; i < offsetBindingPointerVector.size(); i++)
        {
            bos->writeInt(offsetBindingPointerVector[i].id().value);
            bos->writeInt(offsetBindingPointerVector[i].getOffset());
            bos->writeInt(offsetBindingPointerVector[i].getSize());
        }
    }
    
    template void SerializeOffsetBindingPointerVector<gl::Buffer>(
        gl::BinaryOutputStream *bos,
        const std::vector<gl::OffsetBindingPointer<gl::Buffer>> &offsetBindingPointerVector);
    
    template <class ObjectType>
    void SerializeBindingPointerVector(
        gl::BinaryOutputStream *bos,
        const std::vector<gl::BindingPointer<ObjectType>> &bindingPointerVector)
    {
        for (size_t i = 0; i < bindingPointerVector.size(); i++)
        {
            bos->writeInt(bindingPointerVector[i].id().value);
        }
    }
    
    template void SerializeBindingPointerVector<gl::Texture>(
        gl::BinaryOutputStream *bos,
        const std::vector<gl::BindingPointer<gl::Texture>> &bindingPointerVector);
    
    template void SerializeBindingPointerVector<gl::Sampler>(
        gl::BinaryOutputStream *bos,
        const std::vector<gl::BindingPointer<gl::Sampler>> &bindingPointerVector);
    
    bool IsValidColorAttachmentBinding(GLenum binding, size_t colorAttachmentsCount)
    {
        return binding == GL_BACK || (binding >= GL_COLOR_ATTACHMENT0 &&
                                      (binding - GL_COLOR_ATTACHMENT0) < colorAttachmentsCount);
    }
    
    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(gl::BinaryOutputStream *bos, const gl::ImageIndex &imageIndex)
    {
        bos->writeEnum(imageIndex.getType());
        bos->writeInt(imageIndex.getLevelIndex());
        bos->writeInt(imageIndex.getLayerIndex());
        bos->writeInt(imageIndex.getLayerCount());
    }
    
    Result SerializeFramebufferAttachment(const gl::Context *context,
                                          gl::BinaryOutputStream *bos,
                                          ScratchBuffer *scratchBuffer,
                                          gl::Framebuffer *framebuffer,
                                          const gl::FramebufferAttachment &framebufferAttachment)
    {
        bos->writeInt(framebufferAttachment.type());
        // serialize target variable
        bos->writeInt(framebufferAttachment.getBinding());
        if (framebufferAttachment.type() == GL_TEXTURE)
        {
            SerializeImageIndex(bos, framebufferAttachment.getTextureImageIndex());
        }
        bos->writeInt(framebufferAttachment.getNumViews());
        bos->writeInt(framebufferAttachment.isMultiview());
        bos->writeInt(framebufferAttachment.getBaseViewIndex());
        bos->writeInt(framebufferAttachment.getRenderToTextureSamples());
    
        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));
        }
        MemoryBuffer *pixelsPtr = nullptr;
        ANGLE_TRY(ReadPixelsFromAttachment(context, framebuffer, framebufferAttachment, scratchBuffer,
                                           &pixelsPtr));
        bos->writeBytes(pixelsPtr->data(), pixelsPtr->size());
        // Reset framebuffer state
        framebuffer->setReadBuffer(prevReadBufferState);
        return Result::Continue;
    }
    
    Result SerializeFramebufferState(const gl::Context *context,
                                     gl::BinaryOutputStream *bos,
                                     ScratchBuffer *scratchBuffer,
                                     gl::Framebuffer *framebuffer,
                                     const gl::FramebufferState &framebufferState)
    {
        bos->writeInt(framebufferState.id().value);
        bos->writeString(framebufferState.getLabel());
        bos->writeIntVector(framebufferState.getDrawBufferStates());
        bos->writeInt(framebufferState.getReadBufferState());
        bos->writeInt(framebufferState.getDefaultWidth());
        bos->writeInt(framebufferState.getDefaultHeight());
        bos->writeInt(framebufferState.getDefaultSamples());
        bos->writeInt(framebufferState.getDefaultFixedSampleLocations());
        bos->writeInt(framebufferState.getDefaultLayers());
    
        const std::vector<gl::FramebufferAttachment> &colorAttachments =
            framebufferState.getColorAttachments();
        for (const gl::FramebufferAttachment &colorAttachment : colorAttachments)
        {
            if (colorAttachment.isAttached())
            {
                ANGLE_TRY(SerializeFramebufferAttachment(context, bos, scratchBuffer, framebuffer,
                                                         colorAttachment));
            }
        }
        if (framebuffer->getDepthStencilAttachment())
        {
            ANGLE_TRY(SerializeFramebufferAttachment(context, bos, scratchBuffer, framebuffer,
                                                     *framebuffer->getDepthStencilAttachment()));
        }
        else
        {
            if (framebuffer->getDepthAttachment())
            {
                ANGLE_TRY(SerializeFramebufferAttachment(context, bos, scratchBuffer, framebuffer,
                                                         *framebuffer->getDepthAttachment()));
            }
            if (framebuffer->getStencilAttachment())
            {
                ANGLE_TRY(SerializeFramebufferAttachment(context, bos, scratchBuffer, framebuffer,
                                                         *framebuffer->getStencilAttachment()));
            }
        }
        return Result::Continue;
    }
    
    Result SerializeFramebuffer(const gl::Context *context,
                                gl::BinaryOutputStream *bos,
                                ScratchBuffer *scratchBuffer,
                                gl::Framebuffer *framebuffer)
    {
        return SerializeFramebufferState(context, bos, scratchBuffer, framebuffer,
                                         framebuffer->getState());
    }
    
    void SerializeRasterizerState(gl::BinaryOutputStream *bos,
                                  const gl::RasterizerState &rasterizerState)
    {
        bos->writeInt(rasterizerState.cullFace);
        bos->writeEnum(rasterizerState.cullMode);
        bos->writeInt(rasterizerState.frontFace);
        bos->writeInt(rasterizerState.polygonOffsetFill);
        bos->writeInt(rasterizerState.polygonOffsetFactor);
        bos->writeInt(rasterizerState.polygonOffsetUnits);
        bos->writeInt(rasterizerState.pointDrawMode);
        bos->writeInt(rasterizerState.multiSample);
        bos->writeInt(rasterizerState.rasterizerDiscard);
        bos->writeInt(rasterizerState.dither);
    }
    
    void SerializeRectangle(gl::BinaryOutputStream *bos, const gl::Rectangle &rectangle)
    {
        bos->writeInt(rectangle.x);
        bos->writeInt(rectangle.y);
        bos->writeInt(rectangle.width);
        bos->writeInt(rectangle.height);
    }
    
    void SerializeBlendState(gl::BinaryOutputStream *bos, const gl::BlendState &blendState)
    {
        bos->writeInt(blendState.blend);
        bos->writeInt(blendState.sourceBlendRGB);
        bos->writeInt(blendState.destBlendRGB);
        bos->writeInt(blendState.sourceBlendAlpha);
        bos->writeInt(blendState.destBlendAlpha);
        bos->writeInt(blendState.blendEquationRGB);
        bos->writeInt(blendState.blendEquationAlpha);
        bos->writeInt(blendState.colorMaskRed);
        bos->writeInt(blendState.colorMaskGreen);
        bos->writeInt(blendState.colorMaskBlue);
        bos->writeInt(blendState.colorMaskAlpha);
    }
    
    void SerializeDepthStencilState(gl::BinaryOutputStream *bos,
                                    const gl::DepthStencilState &depthStencilState)
    {
        bos->writeInt(depthStencilState.depthTest);
        bos->writeInt(depthStencilState.depthFunc);
        bos->writeInt(depthStencilState.depthMask);
        bos->writeInt(depthStencilState.stencilTest);
        bos->writeInt(depthStencilState.stencilFunc);
        bos->writeInt(depthStencilState.stencilMask);
        bos->writeInt(depthStencilState.stencilFail);
        bos->writeInt(depthStencilState.stencilPassDepthFail);
        bos->writeInt(depthStencilState.stencilPassDepthPass);
        bos->writeInt(depthStencilState.stencilWritemask);
        bos->writeInt(depthStencilState.stencilBackFunc);
        bos->writeInt(depthStencilState.stencilBackMask);
        bos->writeInt(depthStencilState.stencilBackFail);
        bos->writeInt(depthStencilState.stencilBackPassDepthFail);
        bos->writeInt(depthStencilState.stencilBackPassDepthPass);
        bos->writeInt(depthStencilState.stencilBackWritemask);
    }
    
    void SerializeVertexAttribCurrentValueData(
        gl::BinaryOutputStream *bos,
        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)
        {
            bos->writeInt(vertexAttribCurrentValueData.Values.FloatValues[0]);
            bos->writeInt(vertexAttribCurrentValueData.Values.FloatValues[1]);
            bos->writeInt(vertexAttribCurrentValueData.Values.FloatValues[2]);
            bos->writeInt(vertexAttribCurrentValueData.Values.FloatValues[3]);
        }
        else if (vertexAttribCurrentValueData.Type == gl::VertexAttribType::Int)
        {
            bos->writeInt(vertexAttribCurrentValueData.Values.IntValues[0]);
            bos->writeInt(vertexAttribCurrentValueData.Values.IntValues[1]);
            bos->writeInt(vertexAttribCurrentValueData.Values.IntValues[2]);
            bos->writeInt(vertexAttribCurrentValueData.Values.IntValues[3]);
        }
        else
        {
            bos->writeInt(vertexAttribCurrentValueData.Values.UnsignedIntValues[0]);
            bos->writeInt(vertexAttribCurrentValueData.Values.UnsignedIntValues[1]);
            bos->writeInt(vertexAttribCurrentValueData.Values.UnsignedIntValues[2]);
            bos->writeInt(vertexAttribCurrentValueData.Values.UnsignedIntValues[3]);
        }
    }
    
    void SerializePixelPackState(gl::BinaryOutputStream *bos, const gl::PixelPackState &pixelPackState)
    {
        bos->writeInt(pixelPackState.alignment);
        bos->writeInt(pixelPackState.rowLength);
        bos->writeInt(pixelPackState.skipRows);
        bos->writeInt(pixelPackState.skipPixels);
        bos->writeInt(pixelPackState.imageHeight);
        bos->writeInt(pixelPackState.skipImages);
        bos->writeInt(pixelPackState.reverseRowOrder);
    }
    
    void SerializePixelUnpackState(gl::BinaryOutputStream *bos,
                                   const gl::PixelUnpackState &pixelUnpackState)
    {
        bos->writeInt(pixelUnpackState.alignment);
        bos->writeInt(pixelUnpackState.rowLength);
        bos->writeInt(pixelUnpackState.skipRows);
        bos->writeInt(pixelUnpackState.skipPixels);
        bos->writeInt(pixelUnpackState.imageHeight);
        bos->writeInt(pixelUnpackState.skipImages);
    }
    
    void SerializeImageUnit(gl::BinaryOutputStream *bos, const gl::ImageUnit &imageUnit)
    {
        bos->writeInt(imageUnit.level);
        bos->writeInt(imageUnit.layered);
        bos->writeInt(imageUnit.layer);
        bos->writeInt(imageUnit.access);
        bos->writeInt(imageUnit.format);
        bos->writeInt(imageUnit.texture.id().value);
    }
    
    void SerializeGLContextStates(gl::BinaryOutputStream *bos, const gl::State &state)
    {
        bos->writeInt(state.getContextID());
        bos->writeInt(state.getClientType());
        bos->writeInt(state.getContextPriority());
        bos->writeInt(state.getClientMajorVersion());
        bos->writeInt(state.getClientMinorVersion());
    
        SerializeColor(bos, state.getColorClearValue());
        bos->writeInt(state.getDepthClearValue());
        bos->writeInt(state.getStencilClearValue());
        SerializeRasterizerState(bos, state.getRasterizerState());
        bos->writeInt(state.isScissorTestEnabled());
        SerializeRectangle(bos, state.getScissor());
        const gl::BlendStateArray &blendStateArray = state.getBlendStateArray();
        for (size_t i = 0; i < blendStateArray.size(); i++)
        {
            SerializeBlendState(bos, blendStateArray[i]);
        }
        SerializeColor(bos, state.getBlendColor());
        bos->writeInt(state.isSampleAlphaToCoverageEnabled());
        bos->writeInt(state.isSampleCoverageEnabled());
        bos->writeInt(state.getSampleCoverageValue());
        bos->writeInt(state.getSampleCoverageInvert());
        bos->writeInt(state.isSampleMaskEnabled());
        bos->writeInt(state.getMaxSampleMaskWords());
        const auto &sampleMaskValues = state.getSampleMaskValues();
        for (size_t i = 0; i < sampleMaskValues.size(); i++)
        {
            bos->writeInt(sampleMaskValues[i]);
        }
        SerializeDepthStencilState(bos, state.getDepthStencilState());
        bos->writeInt(state.getStencilRef());
        bos->writeInt(state.getStencilBackRef());
        bos->writeInt(state.getLineWidth());
        bos->writeInt(state.getGenerateMipmapHint());
        bos->writeInt(state.getTextureFilteringHint());
        bos->writeInt(state.getFragmentShaderDerivativeHint());
        bos->writeInt(state.isBindGeneratesResourceEnabled());
        bos->writeInt(state.areClientArraysEnabled());
        SerializeRectangle(bos, state.getViewport());
        bos->writeInt(state.getNearPlane());
        bos->writeInt(state.getFarPlane());
        if (state.getReadFramebuffer())
        {
            bos->writeInt(state.getReadFramebuffer()->id().value);
        }
        if (state.getDrawFramebuffer())
        {
            bos->writeInt(state.getDrawFramebuffer()->id().value);
        }
        bos->writeInt(state.getRenderbufferId().value);
        if (state.getProgram())
        {
            bos->writeInt(state.getProgram()->id().value);
        }
        if (state.getProgramPipeline())
        {
            bos->writeInt(state.getProgramPipeline()->id().value);
        }
        bos->writeEnum(state.getProvokingVertex());
        const std::vector<gl::VertexAttribCurrentValueData> &vertexAttribCurrentValues =
            state.getVertexAttribCurrentValues();
        for (size_t i = 0; i < vertexAttribCurrentValues.size(); i++)
        {
            SerializeVertexAttribCurrentValueData(bos, vertexAttribCurrentValues[i]);
        }
        if (state.getVertexArray())
        {
            bos->writeInt(state.getVertexArray()->id().value);
        }
        bos->writeInt(state.getCurrentValuesTypeMask().to_ulong());
        bos->writeInt(state.getActiveSampler());
        for (const auto &textures : state.getBoundTexturesForCapture())
        {
            SerializeBindingPointerVector<gl::Texture>(bos, textures);
        }
        bos->writeInt(state.getTexturesIncompatibleWithSamplers().to_ulong());
        SerializeBindingPointerVector<gl::Sampler>(bos, state.getSamplers());
        for (const gl::ImageUnit &imageUnit : state.getImageUnits())
        {
            SerializeImageUnit(bos, imageUnit);
        }
        for (const auto &query : state.getActiveQueriesForCapture())
        {
            bos->writeInt(query.id().value);
        }
        for (const auto &boundBuffer : state.getBoundBuffersForCapture())
        {
            bos->writeInt(boundBuffer.id().value);
        }
        SerializeOffsetBindingPointerVector<gl::Buffer>(bos,
                                                        state.getOffsetBindingPointerUniformBuffers());
        SerializeOffsetBindingPointerVector<gl::Buffer>(
            bos, state.getOffsetBindingPointerAtomicCounterBuffers());
        SerializeOffsetBindingPointerVector<gl::Buffer>(
            bos, state.getOffsetBindingPointerShaderStorageBuffers());
        if (state.getCurrentTransformFeedback())
        {
            bos->writeInt(state.getCurrentTransformFeedback()->id().value);
        }
        SerializePixelUnpackState(bos, state.getUnpackState());
        SerializePixelPackState(bos, state.getPackState());
        bos->writeInt(state.isPrimitiveRestartEnabled());
        bos->writeInt(state.isMultisamplingEnabled());
        bos->writeInt(state.isSampleAlphaToOneEnabled());
        bos->writeInt(state.getCoverageModulation());
        bos->writeInt(state.getFramebufferSRGB());
        bos->writeInt(state.isRobustResourceInitEnabled());
        bos->writeInt(state.isProgramBinaryCacheEnabled());
        bos->writeInt(state.isTextureRectangleEnabled());
        bos->writeInt(state.getMaxShaderCompilerThreads());
        bos->writeInt(state.getEnabledClipDistances().to_ulong());
        bos->writeInt(state.getBlendFuncConstantAlphaDrawBuffers().to_ulong());
        bos->writeInt(state.getBlendFuncConstantColorDrawBuffers().to_ulong());
        bos->writeInt(state.noSimultaneousConstantColorAndAlphaBlendFunc());
    }
    
    void SerializeBufferState(gl::BinaryOutputStream *bos, const gl::BufferState &bufferState)
    {
        bos->writeString(bufferState.getLabel());
        bos->writeEnum(bufferState.getUsage());
        bos->writeInt(bufferState.getSize());
        bos->writeInt(bufferState.getAccessFlags());
        bos->writeInt(bufferState.getAccess());
        bos->writeInt(bufferState.isMapped());
        bos->writeInt(bufferState.getMapOffset());
        bos->writeInt(bufferState.getMapLength());
    }
    
    Result SerializeBuffer(const gl::Context *context,
                           gl::BinaryOutputStream *bos,
                           ScratchBuffer *scratchBuffer,
                           gl::Buffer *buffer)
    {
        SerializeBufferState(bos, buffer->getState());
        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()));
        bos->writeBytes(dataPtr->data(), dataPtr->size());
        return Result::Continue;
    }
    
    }  // namespace
    
    Result SerializeContext(gl::BinaryOutputStream *bos, const gl::Context *context)
    {
        SerializeGLContextStates(bos, context->getState());
        ScratchBuffer scratchBuffer(1);
        const gl::FramebufferManager &framebufferManager =
            context->getState().getFramebufferManagerForCapture();
        for (const auto &framebuffer : framebufferManager)
        {
            gl::Framebuffer *framebufferPtr = framebuffer.second;
            ANGLE_TRY(SerializeFramebuffer(context, bos, &scratchBuffer, framebufferPtr));
        }
        const gl::BufferManager &bufferManager = context->getState().getBufferManagerForCapture();
        for (const auto &buffer : bufferManager)
        {
            gl::Buffer *bufferPtr = buffer.second;
            ANGLE_TRY(SerializeBuffer(context, bos, &scratchBuffer, bufferPtr));
        }
        scratchBuffer.clear();
        return Result::Continue;
    }
    
    }  // namespace angle