Commit 86ca5d2b by Charlie Lao Committed by Commit Bot

Vulkan: Add plumbing to render pass when ImageHelper gets deleted

ImageHelper object is not refcounted and garbage collected and endRenderPass call is deferred until next render pass starts. This caused a situation that an ImageHelper object gets deleted while still referenced in the open render pass. This CL make sure that we call into all shared context's open renderpass when an image goes away so that they can take appropriate action for this. Bug: b/169618408 Change-Id: I5075e805980084db82ca3e699462272eee5d2d59 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2443571Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Commit-Queue: Charlie Lao <cclao@google.com>
parent da61c40e
...@@ -773,6 +773,9 @@ ContextVk::~ContextVk() = default; ...@@ -773,6 +773,9 @@ ContextVk::~ContextVk() = default;
void ContextVk::onDestroy(const gl::Context *context) void ContextVk::onDestroy(const gl::Context *context)
{ {
// Remove context from the share group
mShareGroupVk->getShareContextSet()->erase(this);
// This will not destroy any resources. It will release them to be collected after finish. // This will not destroy any resources. It will release them to be collected after finish.
mIncompleteTextures.onDestroy(context); mIncompleteTextures.onDestroy(context);
...@@ -974,6 +977,9 @@ angle::Result ContextVk::initialize() ...@@ -974,6 +977,9 @@ angle::Result ContextVk::initialize()
mStagingBuffer.init(mRenderer, kStagingBufferUsageFlags, stagingBufferAlignment, mStagingBuffer.init(mRenderer, kStagingBufferUsageFlags, stagingBufferAlignment,
kStagingBufferSize, true); kStagingBufferSize, true);
// Add context into the share group
mShareGroupVk->getShareContextSet()->insert(this);
return angle::Result::Continue; return angle::Result::Continue;
} }
......
...@@ -553,6 +553,14 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -553,6 +553,14 @@ class ContextVk : public ContextImpl, public vk::Context
vk::AliasingMode::Allowed, image); vk::AliasingMode::Allowed, image);
} }
void onImageHelperRelease(const vk::ImageHelper *image)
{
if (mRenderPassCommands->started())
{
mRenderPassCommands->onImageHelperRelease(image);
}
}
vk::CommandBuffer &getOutsideRenderPassCommandBuffer() vk::CommandBuffer &getOutsideRenderPassCommandBuffer()
{ {
return mOutsideRenderPassCommands->getCommandBuffer(); return mOutsideRenderPassCommands->getCommandBuffer();
......
...@@ -19,6 +19,8 @@ namespace rx ...@@ -19,6 +19,8 @@ namespace rx
{ {
class RendererVk; class RendererVk;
using ShareContextSet = std::set<ContextVk *>;
class ShareGroupVk : public ShareGroupImpl class ShareGroupVk : public ShareGroupImpl
{ {
public: public:
...@@ -30,6 +32,7 @@ class ShareGroupVk : public ShareGroupImpl ...@@ -30,6 +32,7 @@ class ShareGroupVk : public ShareGroupImpl
// synchronous update to the caches. // synchronous update to the caches.
PipelineLayoutCache &getPipelineLayoutCache() { return mPipelineLayoutCache; } PipelineLayoutCache &getPipelineLayoutCache() { return mPipelineLayoutCache; }
DescriptorSetLayoutCache &getDescriptorSetLayoutCache() { return mDescriptorSetLayoutCache; } DescriptorSetLayoutCache &getDescriptorSetLayoutCache() { return mDescriptorSetLayoutCache; }
ShareContextSet *getShareContextSet() { return &mShareContextSet; }
private: private:
// ANGLE uses a PipelineLayout cache to store compatible pipeline layouts. // ANGLE uses a PipelineLayout cache to store compatible pipeline layouts.
...@@ -37,6 +40,9 @@ class ShareGroupVk : public ShareGroupImpl ...@@ -37,6 +40,9 @@ class ShareGroupVk : public ShareGroupImpl
// DescriptorSetLayouts are also managed in a cache. // DescriptorSetLayouts are also managed in a cache.
DescriptorSetLayoutCache mDescriptorSetLayoutCache; DescriptorSetLayoutCache mDescriptorSetLayoutCache;
// The list of contexts within the share group
ShareContextSet mShareContextSet;
}; };
class DisplayVk : public DisplayImpl, public vk::Context class DisplayVk : public DisplayImpl, public vk::Context
......
...@@ -34,6 +34,8 @@ void ImageVk::onDestroy(const egl::Display *display) ...@@ -34,6 +34,8 @@ void ImageVk::onDestroy(const egl::Display *display)
if (mImage != nullptr && mOwnsImage) if (mImage != nullptr && mOwnsImage)
{ {
// TODO: We need to handle the case that EGLImage used in two context that aren't shared.
// https://issuetracker.google.com/169868803
mImage->releaseImage(renderer); mImage->releaseImage(renderer);
mImage->releaseStagingBuffer(renderer); mImage->releaseStagingBuffer(renderer);
SafeDelete(mImage); SafeDelete(mImage);
......
...@@ -144,7 +144,7 @@ angle::Result OverlayVk::cullWidgets(ContextVk *contextVk) ...@@ -144,7 +144,7 @@ angle::Result OverlayVk::cullWidgets(ContextVk *contextVk)
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
// Release old culledWidgets image // Release old culledWidgets image
mCulledWidgets.releaseImage(renderer); mCulledWidgets.releaseImageFromShareContexts(renderer, contextVk);
contextVk->addGarbage(&mCulledWidgetsView); contextVk->addGarbage(&mCulledWidgetsView);
// Create a buffer to contain coordinates of enabled text and graph widgets. This buffer will // Create a buffer to contain coordinates of enabled text and graph widgets. This buffer will
......
...@@ -227,7 +227,7 @@ void RenderbufferVk::releaseImage(ContextVk *contextVk) ...@@ -227,7 +227,7 @@ void RenderbufferVk::releaseImage(ContextVk *contextVk)
if (mImage && mOwnsImage) if (mImage && mOwnsImage)
{ {
mImage->releaseImage(renderer); mImage->releaseImageFromShareContexts(renderer, contextVk);
mImage->releaseStagingBuffer(renderer); mImage->releaseStagingBuffer(renderer);
} }
else else
...@@ -240,7 +240,7 @@ void RenderbufferVk::releaseImage(ContextVk *contextVk) ...@@ -240,7 +240,7 @@ void RenderbufferVk::releaseImage(ContextVk *contextVk)
if (mMultisampledImage.valid()) if (mMultisampledImage.valid())
{ {
mMultisampledImage.releaseImage(renderer); mMultisampledImage.releaseImageFromShareContexts(renderer, contextVk);
} }
mMultisampledImageViews.release(renderer); mMultisampledImageViews.release(renderer);
} }
......
...@@ -227,6 +227,7 @@ void OffscreenSurfaceVk::AttachmentImage::destroy(const egl::Display *display) ...@@ -227,6 +227,7 @@ void OffscreenSurfaceVk::AttachmentImage::destroy(const egl::Display *display)
{ {
DisplayVk *displayVk = vk::GetImpl(display); DisplayVk *displayVk = vk::GetImpl(display);
RendererVk *renderer = displayVk->getRenderer(); RendererVk *renderer = displayVk->getRenderer();
// Front end must ensure all usage has been submitted.
image.releaseImage(renderer); image.releaseImage(renderer);
image.releaseStagingBuffer(renderer); image.releaseStagingBuffer(renderer);
imageViews.release(renderer); imageViews.release(renderer);
...@@ -1065,14 +1066,14 @@ void WindowSurfaceVk::releaseSwapchainImages(ContextVk *contextVk) ...@@ -1065,14 +1066,14 @@ void WindowSurfaceVk::releaseSwapchainImages(ContextVk *contextVk)
if (mDepthStencilImage.valid()) if (mDepthStencilImage.valid())
{ {
mDepthStencilImage.releaseImage(renderer); mDepthStencilImage.releaseImageFromShareContexts(renderer, contextVk);
mDepthStencilImage.releaseStagingBuffer(renderer); mDepthStencilImage.releaseStagingBuffer(renderer);
mDepthStencilImageViews.release(renderer); mDepthStencilImageViews.release(renderer);
} }
if (mColorImageMS.valid()) if (mColorImageMS.valid())
{ {
mColorImageMS.releaseImage(renderer); mColorImageMS.releaseImageFromShareContexts(renderer, contextVk);
mColorImageMS.releaseStagingBuffer(renderer); mColorImageMS.releaseStagingBuffer(renderer);
mColorImageMSViews.release(renderer); mColorImageMSViews.release(renderer);
contextVk->addGarbage(&mFramebufferMS); contextVk->addGarbage(&mFramebufferMS);
......
...@@ -2382,7 +2382,7 @@ void TextureVk::releaseImage(ContextVk *contextVk) ...@@ -2382,7 +2382,7 @@ void TextureVk::releaseImage(ContextVk *contextVk)
{ {
if (mOwnsImage) if (mOwnsImage)
{ {
mImage->releaseImage(renderer); mImage->releaseImageFromShareContexts(renderer, contextVk);
} }
else else
{ {
...@@ -2395,7 +2395,7 @@ void TextureVk::releaseImage(ContextVk *contextVk) ...@@ -2395,7 +2395,7 @@ void TextureVk::releaseImage(ContextVk *contextVk)
{ {
if (image.valid()) if (image.valid())
{ {
image.releaseImage(renderer); image.releaseImageFromShareContexts(renderer, contextVk);
} }
} }
......
...@@ -313,6 +313,8 @@ void HardwareBufferImageSiblingVkAndroid::release(RendererVk *renderer) ...@@ -313,6 +313,8 @@ void HardwareBufferImageSiblingVkAndroid::release(RendererVk *renderer)
{ {
if (mImage != nullptr) if (mImage != nullptr)
{ {
// TODO: We need to handle the case that EGLImage used in two context that aren't shared.
// https://issuetracker.google.com/169868803
mImage->releaseImage(renderer); mImage->releaseImage(renderer);
mImage->releaseStagingBuffer(renderer); mImage->releaseStagingBuffer(renderer);
SafeDelete(mImage); SafeDelete(mImage);
......
...@@ -872,6 +872,13 @@ void CommandBufferHelper::executeBarriers(ContextVk *contextVk, PrimaryCommandBu ...@@ -872,6 +872,13 @@ void CommandBufferHelper::executeBarriers(ContextVk *contextVk, PrimaryCommandBu
mPipelineBarrierMask.reset(); mPipelineBarrierMask.reset();
} }
void CommandBufferHelper::onImageHelperRelease(const vk::ImageHelper *image)
{
ASSERT(mIsRenderPassCommandBuffer);
// TODO: https://issuetracker.google.com/168953278 We will use this to finalize image layout
// transition
}
void CommandBufferHelper::beginRenderPass(const Framebuffer &framebuffer, void CommandBufferHelper::beginRenderPass(const Framebuffer &framebuffer,
const gl::Rectangle &renderArea, const gl::Rectangle &renderArea,
const RenderPassDesc &renderPassDesc, const RenderPassDesc &renderPassDesc,
...@@ -3044,6 +3051,21 @@ void ImageHelper::releaseImage(RendererVk *renderer) ...@@ -3044,6 +3051,21 @@ void ImageHelper::releaseImage(RendererVk *renderer)
mImageSerial = kInvalidImageSerial; mImageSerial = kInvalidImageSerial;
} }
void ImageHelper::releaseImageFromShareContexts(RendererVk *renderer, ContextVk *contextVk)
{
if (contextVk && mImageSerial.valid())
{
ShareContextSet &shareContextSet = *contextVk->getShareGroupVk()->getShareContextSet();
for (ContextVk *ctx : shareContextSet)
{
ctx->onImageHelperRelease(this);
}
}
renderer->collectGarbageAndReinit(&mUse, &mImage, &mDeviceMemory);
mImageSerial = kInvalidImageSerial;
}
void ImageHelper::releaseStagingBuffer(RendererVk *renderer) void ImageHelper::releaseStagingBuffer(RendererVk *renderer)
{ {
// Remove updates that never made it to the texture. // Remove updates that never made it to the texture.
...@@ -5311,6 +5333,7 @@ void ImageHelper::SubresourceUpdate::release(RendererVk *renderer) ...@@ -5311,6 +5333,7 @@ void ImageHelper::SubresourceUpdate::release(RendererVk *renderer)
{ {
if (updateSource == UpdateSource::Image) if (updateSource == UpdateSource::Image)
{ {
// Staging images won't be used in render pass attachments.
image.image->releaseImage(renderer); image.image->releaseImage(renderer);
image.image->releaseStagingBuffer(renderer); image.image->releaseStagingBuffer(renderer);
SafeDelete(image.image); SafeDelete(image.image);
......
...@@ -987,6 +987,8 @@ class CommandBufferHelper : angle::NonCopyable ...@@ -987,6 +987,8 @@ class CommandBufferHelper : angle::NonCopyable
return mRenderPassStarted; return mRenderPassStarted;
} }
void onImageHelperRelease(const vk::ImageHelper *image);
void beginRenderPass(const Framebuffer &framebuffer, void beginRenderPass(const Framebuffer &framebuffer,
const gl::Rectangle &renderArea, const gl::Rectangle &renderArea,
const RenderPassDesc &renderPassDesc, const RenderPassDesc &renderPassDesc,
...@@ -1319,8 +1321,11 @@ class ImageHelper final : public Resource, public angle::Subject ...@@ -1319,8 +1321,11 @@ class ImageHelper final : public Resource, public angle::Subject
gl::TextureType textureType, gl::TextureType textureType,
GLint samples, GLint samples,
const ImageHelper &resolveImage); const ImageHelper &resolveImage);
// Release the underlining VkImage object for garbage collection.
void releaseImage(RendererVk *rendererVk); void releaseImage(RendererVk *renderer);
// Similar to releaseImage, but also notify all contexts in the same share group to stop
// accessing to it.
void releaseImageFromShareContexts(RendererVk *renderer, ContextVk *contextVk);
void releaseStagingBuffer(RendererVk *renderer); void releaseStagingBuffer(RendererVk *renderer);
bool valid() const { return mImage.valid(); } bool valid() const { return mImage.valid(); }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment