Edit

kc3-lang/angle/src/libANGLE/renderer/vulkan/ImageVk.cpp

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2019-06-25 17:11:58
    Hash : c773ab98
    Message : Vulkan: Recycle dynamic buffer storage. This adds a free list to the dynamic buffer storage. Buffers are added to the free list when the retained buffers are released. They are taken from the free list when we allocate a new buffer. We only allocate a new buffer in the ring when we run out of free buffers. This reduces the amount of time we spend in allocation for frequent updates. Now that we're recycling buffers inside of DynamicBuffer we also need to be a bit more careful about when we allow ourselves to reuse them. If they're still in use by the GPU we should not try to modify them. Bug: angleproject:3082 Change-Id: Ibee5a7e2fe4a17f4a2f7af6bc6bcce54bdc413c2 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1646548 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Tobin Ehlis <tobine@google.com>

  • src/libANGLE/renderer/vulkan/ImageVk.cpp
  • //
    // Copyright 2016 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.
    //
    // ImageVk.cpp:
    //    Implements the class methods for ImageVk.
    //
    
    #include "libANGLE/renderer/vulkan/ImageVk.h"
    
    #include "common/debug.h"
    #include "libANGLE/Context.h"
    #include "libANGLE/Display.h"
    #include "libANGLE/renderer/vulkan/ContextVk.h"
    #include "libANGLE/renderer/vulkan/DisplayVk.h"
    #include "libANGLE/renderer/vulkan/RenderbufferVk.h"
    #include "libANGLE/renderer/vulkan/TextureVk.h"
    #include "libANGLE/renderer/vulkan/vk_utils.h"
    
    namespace rx
    {
    
    ImageVk::ImageVk(const egl::ImageState &state, const gl::Context *context)
        : ImageImpl(state), mImageLevel(0), mOwnsImage(false), mImage(nullptr), mContext(context)
    {}
    
    ImageVk::~ImageVk() {}
    
    void ImageVk::onDestroy(const egl::Display *display)
    {
        DisplayVk *displayVk = vk::GetImpl(display);
        RendererVk *renderer = displayVk->getRenderer();
    
        std::vector<vk::GarbageObjectBase> garbage;
    
        if (mImage != nullptr && mOwnsImage)
        {
            mImage->releaseImage(displayVk, &garbage);
            mImage->releaseStagingBuffer(displayVk, &garbage);
            delete mImage;
        }
        else if (egl::IsExternalImageTarget(mState.target))
        {
            ASSERT(mState.source != nullptr);
            ExternalImageSiblingVk *externalImageSibling =
                GetImplAs<ExternalImageSiblingVk>(GetAs<egl::ExternalImageSibling>(mState.source));
            externalImageSibling->release(displayVk, &garbage);
        }
        mImage = nullptr;
    
        if (!garbage.empty())
        {
            renderer->addGarbage(std::move(mImageLastUseFences), std::move(garbage));
        }
        else
        {
            for (vk::Shared<vk::Fence> &fence : mImageLastUseFences)
            {
                fence.reset(displayVk->getDevice());
            }
        }
    }
    
    egl::Error ImageVk::initialize(const egl::Display *display)
    {
        if (egl::IsTextureTarget(mState.target))
        {
            TextureVk *textureVk = GetImplAs<TextureVk>(GetAs<gl::Texture>(mState.source));
    
            // Make sure the texture has created its backing storage
            ASSERT(mContext != nullptr);
            ContextVk *contextVk = vk::GetImpl(mContext);
            ANGLE_TRY(ResultToEGL(textureVk->ensureImageInitialized(contextVk)));
    
            mImage = &textureVk->getImage();
    
            // The staging buffer for a texture source should already be initialized
    
            mOwnsImage = false;
    
            mImageTextureType = mState.imageIndex.getType();
            mImageLevel       = mState.imageIndex.getLevelIndex();
            mImageLayer       = mState.imageIndex.hasLayer() ? mState.imageIndex.getLayerIndex() : 0;
        }
        else
        {
            RendererVk *renderer = nullptr;
            if (egl::IsRenderbufferTarget(mState.target))
            {
                RenderbufferVk *renderbufferVk =
                    GetImplAs<RenderbufferVk>(GetAs<gl::Renderbuffer>(mState.source));
                mImage = renderbufferVk->getImage();
    
                ASSERT(mContext != nullptr);
                renderer = vk::GetImpl(mContext)->getRenderer();
                ;
            }
            else if (egl::IsExternalImageTarget(mState.target))
            {
                const ExternalImageSiblingVk *externalImageSibling =
                    GetImplAs<ExternalImageSiblingVk>(GetAs<egl::ExternalImageSibling>(mState.source));
                mImage = externalImageSibling->getImage();
    
                ASSERT(mContext == nullptr);
                renderer = vk::GetImpl(display)->getRenderer();
            }
            else
            {
                UNREACHABLE();
                return egl::EglBadAccess();
            }
    
            // Make sure a staging buffer is ready to use to upload data
            mImage->initStagingBuffer(renderer, mImage->getFormat(), vk::kStagingBufferFlags,
                                      vk::kStagingBufferSize);
    
            mOwnsImage = false;
    
            mImageTextureType = gl::TextureType::_2D;
            mImageLevel       = 0;
            mImageLayer       = 0;
        }
    
        return egl::NoError();
    }
    
    angle::Result ImageVk::orphan(const gl::Context *context, egl::ImageSibling *sibling)
    {
        if (sibling == mState.source)
        {
            if (egl::IsTextureTarget(mState.target))
            {
                TextureVk *textureVk = GetImplAs<TextureVk>(GetAs<gl::Texture>(mState.source));
                ASSERT(mImage == &textureVk->getImage());
                textureVk->releaseOwnershipOfImage(context);
                mOwnsImage = true;
            }
            else if (egl::IsRenderbufferTarget(mState.target))
            {
                RenderbufferVk *renderbufferVk =
                    GetImplAs<RenderbufferVk>(GetAs<gl::Renderbuffer>(mState.source));
                ASSERT(mImage == renderbufferVk->getImage());
                renderbufferVk->releaseOwnershipOfImage(context);
                mOwnsImage = true;
            }
            else
            {
                ANGLE_VK_UNREACHABLE(vk::GetImpl(context));
                return angle::Result::Stop;
            }
        }
    
        // Grab a fence from the releasing context to know when the image is no longer used
        ASSERT(mContext != nullptr);
        ContextVk *contextVk = vk::GetImpl(mContext);
    
        // Flush the context to make sure the fence has been submitted.
        ANGLE_TRY(contextVk->flushImpl(nullptr));
    
        vk::Shared<vk::Fence> fence = contextVk->getLastSubmittedFence();
        if (fence.isReferenced())
        {
            mImageLastUseFences.push_back(std::move(fence));
        }
    
        return angle::Result::Continue;
    }
    
    }  // namespace rx