Edit

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

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2017-10-03 09:01:44
    Hash : 05b35b21
    Message : D3D11: Lazy robust resource init. This patch moves the robust resource init logic to the GL front-end. Instead of initializing texture resources immediately on creation in D3D11, it defers the clear until before a draw call in some cases, or skips the update if we can determine if a texture (or other resource) has been fully initialized. Currently lazy init is only implemented for Textures, Renderbuffers, and Surfaces. Various places where lazy resource init is triggered: * Framebuffer operations (Draw, Blit, CopyTexImage, Clear, ReadPixels) * Texture operations (SubImage, GenerateMipmap, CopyTexImage) Some efficiency gains remain to be implemented, such as when a SubImage call fills the entire object. Similarly for Blit, and a few other operations. In these cases we can skip lazy init as an optimization. Edge cases with EGLImage are mostly untested. BUG=angleproject:2107 Change-Id: I2bf3a69b1eae0d4feeb5b17daca23451f1037be8 Reviewed-on: https://chromium-review.googlesource.com/576058 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org>

  • src/libANGLE/FramebufferAttachment.cpp
  • //
    // Copyright (c) 2014 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.
    //
    
    // FramebufferAttachment.cpp: the gl::FramebufferAttachment class and its derived classes
    // objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108.
    
    #include "libANGLE/FramebufferAttachment.h"
    
    #include "common/utilities.h"
    #include "libANGLE/Config.h"
    #include "libANGLE/Context.h"
    #include "libANGLE/Renderbuffer.h"
    #include "libANGLE/Surface.h"
    #include "libANGLE/Texture.h"
    #include "libANGLE/formatutils.h"
    #include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h"
    #include "libANGLE/renderer/FramebufferImpl.h"
    
    namespace gl
    {
    
    namespace
    {
    
    std::vector<Offset> TransformViewportOffsetArrayToVectorOfOffsets(const GLint *viewportOffsets,
                                                                      GLsizei numViews)
    {
        const size_t numViewsAsSizeT = static_cast<size_t>(numViews);
        std::vector<Offset> offsetVector;
        offsetVector.reserve(numViewsAsSizeT);
        for (size_t i = 0u; i < numViewsAsSizeT; ++i)
        {
            offsetVector.emplace_back(Offset(viewportOffsets[i * 2u], viewportOffsets[i * 2u + 1u], 0));
        }
        return offsetVector;
    }
    
    }  // namespace
    
    ////// FramebufferAttachment::Target Implementation //////
    
    const GLsizei FramebufferAttachment::kDefaultNumViews         = 1;
    const GLenum FramebufferAttachment::kDefaultMultiviewLayout   = GL_NONE;
    const GLint FramebufferAttachment::kDefaultBaseViewIndex      = 0;
    const GLint FramebufferAttachment::kDefaultViewportOffsets[2] = {0};
    
    std::vector<Offset> FramebufferAttachment::GetDefaultViewportOffsetVector()
    {
        return TransformViewportOffsetArrayToVectorOfOffsets(
            FramebufferAttachment::kDefaultViewportOffsets, FramebufferAttachment::kDefaultNumViews);
    }
    
    FramebufferAttachment::Target::Target()
        : mBinding(GL_NONE),
          mTextureIndex(ImageIndex::MakeInvalid())
    {
    }
    
    FramebufferAttachment::Target::Target(GLenum binding, const ImageIndex &imageIndex)
        : mBinding(binding),
          mTextureIndex(imageIndex)
    {
    }
    
    FramebufferAttachment::Target::Target(const Target &other)
        : mBinding(other.mBinding),
          mTextureIndex(other.mTextureIndex)
    {
    }
    
    FramebufferAttachment::Target &FramebufferAttachment::Target::operator=(const Target &other)
    {
        this->mBinding = other.mBinding;
        this->mTextureIndex = other.mTextureIndex;
        return *this;
    }
    
    ////// FramebufferAttachment Implementation //////
    
    FramebufferAttachment::FramebufferAttachment()
        : mType(GL_NONE),
          mResource(nullptr),
          mNumViews(kDefaultNumViews),
          mMultiviewLayout(kDefaultMultiviewLayout),
          mBaseViewIndex(kDefaultBaseViewIndex),
          mViewportOffsets(GetDefaultViewportOffsetVector())
    {
    }
    
    FramebufferAttachment::FramebufferAttachment(const Context *context,
                                                 GLenum type,
                                                 GLenum binding,
                                                 const ImageIndex &textureIndex,
                                                 FramebufferAttachmentObject *resource)
        : mResource(nullptr)
    {
        attach(context, type, binding, textureIndex, resource, kDefaultNumViews, kDefaultBaseViewIndex,
               kDefaultMultiviewLayout, kDefaultViewportOffsets);
    }
    
    FramebufferAttachment::FramebufferAttachment(FramebufferAttachment &&other)
        : FramebufferAttachment()
    {
        *this = std::move(other);
    }
    
    FramebufferAttachment &FramebufferAttachment::operator=(FramebufferAttachment &&other)
    {
        std::swap(mType, other.mType);
        std::swap(mTarget, other.mTarget);
        std::swap(mResource, other.mResource);
        std::swap(mNumViews, other.mNumViews);
        std::swap(mMultiviewLayout, other.mMultiviewLayout);
        std::swap(mBaseViewIndex, other.mBaseViewIndex);
        std::swap(mViewportOffsets, other.mViewportOffsets);
        return *this;
    }
    
    FramebufferAttachment::~FramebufferAttachment()
    {
        ASSERT(!isAttached());
    }
    
    void FramebufferAttachment::detach(const Context *context)
    {
        mType = GL_NONE;
        if (mResource != nullptr)
        {
            mResource->onDetach(context);
            mResource = nullptr;
        }
        mNumViews        = kDefaultNumViews;
        mMultiviewLayout = kDefaultMultiviewLayout;
        mBaseViewIndex   = kDefaultBaseViewIndex;
        mViewportOffsets = GetDefaultViewportOffsetVector();
    
        // not technically necessary, could omit for performance
        mTarget = Target();
    }
    
    void FramebufferAttachment::attach(const Context *context,
                                       GLenum type,
                                       GLenum binding,
                                       const ImageIndex &textureIndex,
                                       FramebufferAttachmentObject *resource,
                                       GLsizei numViews,
                                       GLuint baseViewIndex,
                                       GLenum multiviewLayout,
                                       const GLint *viewportOffsets)
    {
        if (resource == nullptr)
        {
            detach(context);
            return;
        }
    
        mType = type;
        mTarget = Target(binding, textureIndex);
        mNumViews        = numViews;
        mBaseViewIndex   = baseViewIndex;
        mMultiviewLayout = multiviewLayout;
        if (multiviewLayout == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE)
        {
            mViewportOffsets = TransformViewportOffsetArrayToVectorOfOffsets(viewportOffsets, numViews);
        }
        else
        {
            mViewportOffsets = GetDefaultViewportOffsetVector();
        }
        resource->onAttach(context);
    
        if (mResource != nullptr)
        {
            mResource->onDetach(context);
        }
    
        mResource = resource;
    }
    
    GLuint FramebufferAttachment::getRedSize() const
    {
        return getFormat().info->redBits;
    }
    
    GLuint FramebufferAttachment::getGreenSize() const
    {
        return getFormat().info->greenBits;
    }
    
    GLuint FramebufferAttachment::getBlueSize() const
    {
        return getFormat().info->blueBits;
    }
    
    GLuint FramebufferAttachment::getAlphaSize() const
    {
        return getFormat().info->alphaBits;
    }
    
    GLuint FramebufferAttachment::getDepthSize() const
    {
        return getFormat().info->depthBits;
    }
    
    GLuint FramebufferAttachment::getStencilSize() const
    {
        return getFormat().info->stencilBits;
    }
    
    GLenum FramebufferAttachment::getComponentType() const
    {
        return getFormat().info->componentType;
    }
    
    GLenum FramebufferAttachment::getColorEncoding() const
    {
        return getFormat().info->colorEncoding;
    }
    
    GLuint FramebufferAttachment::id() const
    {
        return mResource->getId();
    }
    
    const ImageIndex &FramebufferAttachment::getTextureImageIndex() const
    {
        ASSERT(type() == GL_TEXTURE);
        return mTarget.textureIndex();
    }
    
    GLenum FramebufferAttachment::cubeMapFace() const
    {
        ASSERT(mType == GL_TEXTURE);
    
        const auto &index = mTarget.textureIndex();
        return IsCubeMapTextureTarget(index.type) ? index.type : GL_NONE;
    }
    
    GLint FramebufferAttachment::mipLevel() const
    {
        ASSERT(type() == GL_TEXTURE);
        return mTarget.textureIndex().mipIndex;
    }
    
    GLint FramebufferAttachment::layer() const
    {
        ASSERT(mType == GL_TEXTURE);
    
        const auto &index = mTarget.textureIndex();
    
        if (index.type == GL_TEXTURE_2D_ARRAY || index.type == GL_TEXTURE_3D)
        {
            return index.layerIndex;
        }
        return 0;
    }
    
    GLsizei FramebufferAttachment::getNumViews() const
    {
        return mNumViews;
    }
    
    GLenum FramebufferAttachment::getMultiviewLayout() const
    {
        return mMultiviewLayout;
    }
    
    GLint FramebufferAttachment::getBaseViewIndex() const
    {
        return mBaseViewIndex;
    }
    
    const std::vector<Offset> &FramebufferAttachment::getMultiviewViewportOffsets() const
    {
        return mViewportOffsets;
    }
    
    Texture *FramebufferAttachment::getTexture() const
    {
        return rx::GetAs<Texture>(mResource);
    }
    
    Renderbuffer *FramebufferAttachment::getRenderbuffer() const
    {
        return rx::GetAs<Renderbuffer>(mResource);
    }
    
    const egl::Surface *FramebufferAttachment::getSurface() const
    {
        return rx::GetAs<egl::Surface>(mResource);
    }
    
    FramebufferAttachmentObject *FramebufferAttachment::getResource() const
    {
        return mResource;
    }
    
    bool FramebufferAttachment::operator==(const FramebufferAttachment &other) const
    {
        if (mResource != other.mResource || mType != other.mType || mNumViews != other.mNumViews ||
            mMultiviewLayout != other.mMultiviewLayout || mBaseViewIndex != other.mBaseViewIndex ||
            mViewportOffsets != other.mViewportOffsets)
        {
            return false;
        }
    
        if (mType == GL_TEXTURE && getTextureImageIndex() != other.getTextureImageIndex())
        {
            return false;
        }
    
        return true;
    }
    
    bool FramebufferAttachment::operator!=(const FramebufferAttachment &other) const
    {
        return !(*this == other);
    }
    
    InitState FramebufferAttachment::initState() const
    {
        return mResource ? mResource->initState(mTarget.textureIndex()) : InitState::Initialized;
    }
    
    Error FramebufferAttachment::initializeContents(const Context *context)
    {
        ASSERT(mResource);
        ANGLE_TRY(mResource->initializeContents(context, mTarget.textureIndex()));
        setInitState(InitState::Initialized);
        return NoError();
    }
    
    void FramebufferAttachment::setInitState(InitState initState) const
    {
        ASSERT(mResource);
        mResource->setInitState(mTarget.textureIndex(), initState);
    }
    
    ////// FramebufferAttachmentObject Implementation //////
    
    FramebufferAttachmentObject::FramebufferAttachmentObject()
    {
    }
    
    FramebufferAttachmentObject::~FramebufferAttachmentObject()
    {
    }
    
    Error FramebufferAttachmentObject::getAttachmentRenderTarget(
        const Context *context,
        GLenum binding,
        const ImageIndex &imageIndex,
        rx::FramebufferAttachmentRenderTarget **rtOut) const
    {
        return getAttachmentImpl()->getAttachmentRenderTarget(context, binding, imageIndex, rtOut);
    }
    
    OnAttachmentDirtyChannel *FramebufferAttachmentObject::getDirtyChannel()
    {
        return &mDirtyChannel;
    }
    
    Error FramebufferAttachmentObject::initializeContents(const Context *context,
                                                          const ImageIndex &imageIndex)
    {
        ASSERT(context->isRobustResourceInitEnabled());
    
        // Because gl::Texture cannot support tracking individual layer dirtiness, we only handle
        // initializing entire mip levels for 2D array textures.
        if (imageIndex.type == GL_TEXTURE_2D_ARRAY && imageIndex.hasLayer())
        {
            ImageIndex fullMipIndex = imageIndex;
            fullMipIndex.layerIndex = ImageIndex::ENTIRE_LEVEL;
            return getAttachmentImpl()->initializeContents(context, fullMipIndex);
        }
        else
        {
            return getAttachmentImpl()->initializeContents(context, imageIndex);
        }
    }
    
    }  // namespace gl