Commit 68591eff by Jamie Madill Committed by Commit Bot

Vulkan: Store ImageView access in the graph.

This will ensure we don't destroy the image views when they are still in use by other Contexts. Bug: angleproject:2464 Change-Id: I1d3ba2ad241250e31ea32873446c4cb23971750d Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1843236Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent f939cb63
......@@ -717,7 +717,9 @@ ANGLE_INLINE bool CommandGraphResource::hasChildlessWritingNode() const
// CommandGraph inlines.
ANGLE_INLINE void CommandGraph::onResourceUse(const SharedResourceUse &resourceUse)
{
ASSERT(!empty());
// Disabled the assert because of difficulties with ImageView references.
// TODO(jmadill): Clean up with graph redesign. http://anglebug.com/4029
// ASSERT(!empty());
SharedResourceUse newUse;
newUse.set(resourceUse);
mResourceUses.emplace_back(std::move(newUse));
......
......@@ -2959,6 +2959,7 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context,
image.changeLayout(aspectFlags, textureLayout, srcLayoutChange);
}
textureVk->onImageViewGraphAccess(&mCommandGraph);
image.addReadDependency(this, recorder);
mActiveTextures[textureUnit].texture = textureVk;
......
......@@ -823,6 +823,7 @@ angle::Result FramebufferVk::blit(const gl::Context *context,
{
const vk::ImageView *readImageView = nullptr;
ANGLE_TRY(readRenderTarget->getImageView(contextVk, &readImageView));
readRenderTarget->onImageViewGraphAccess(contextVk);
ANGLE_TRY(utilsVk.colorBlitResolve(contextVk, this, &readRenderTarget->getImage(),
readImageView, params));
}
......@@ -1578,10 +1579,12 @@ angle::Result FramebufferVk::readPixelsImpl(ContextVk *contextVk,
gl::Extents FramebufferVk::getReadImageExtents() const
{
ASSERT(getColorReadRenderTarget()->getExtents().width == mState.getDimensions().width);
ASSERT(getColorReadRenderTarget()->getExtents().height == mState.getDimensions().height);
RenderTargetVk *readRenderTarget = mRenderTargetCache.getColorRead(mState);
return getColorReadRenderTarget()->getExtents();
ASSERT(readRenderTarget->getExtents().width == mState.getDimensions().width);
ASSERT(readRenderTarget->getExtents().height == mState.getDimensions().height);
return readRenderTarget->getExtents();
}
gl::Rectangle FramebufferVk::getCompleteRenderArea() const
......
......@@ -1648,16 +1648,23 @@ angle::Result ProgramVk::updateTexturesDescriptorSet(ContextVk *contextVk)
VkDescriptorImageInfo &imageInfo = descriptorImageInfo[writeCount];
// Use bound sampler object if one present, otherwise use texture's sampler
imageInfo.sampler = (samplerVk != nullptr) ? samplerVk->getSampler().getHandle()
: textureVk->getSampler().getHandle();
imageInfo.imageView = textureVk->getReadImageView().getHandle();
const vk::Sampler &sampler =
(samplerVk != nullptr) ? samplerVk->getSampler() : textureVk->getSampler();
imageInfo.sampler = sampler.getHandle();
imageInfo.imageLayout = image.getCurrentLayout();
if (emulateSeamfulCubeMapSampling)
{
// If emulating seamful cubemapping, use the fetch image view. This is basically
// the same image view as read, except it's a 2DArray view for cube maps.
imageInfo.imageView = textureVk->getFetchImageView().getHandle();
imageInfo.imageView =
textureVk->getFetchImageViewAndRecordUse(contextVk).getHandle();
}
else
{
imageInfo.imageView =
textureVk->getReadImageViewAndRecordUse(contextVk).getHandle();
}
VkWriteDescriptorSet &writeInfo = writeDescriptorInfo[writeCount];
......
......@@ -28,7 +28,12 @@ RenderTargetVk::RenderTargetVk(RenderTargetVk &&other)
mImageViews(other.mImageViews),
mLevelIndex(other.mLevelIndex),
mLayerIndex(other.mLayerIndex)
{}
{
other.mImage = nullptr;
other.mImageViews = nullptr;
other.mLevelIndex = 0;
other.mLayerIndex = 0;
}
void RenderTargetVk::init(vk::ImageHelper *image,
vk::ImageViewHelper *imageViews,
......@@ -63,6 +68,8 @@ angle::Result RenderTargetVk::onColorDraw(ContextVk *contextVk,
// Set up dependencies between the RT resource and the Framebuffer.
mImage->addWriteDependency(contextVk, framebufferVk);
onImageViewGraphAccess(contextVk);
return angle::Result::Continue;
}
......@@ -82,6 +89,8 @@ angle::Result RenderTargetVk::onDepthStencilDraw(ContextVk *contextVk,
// Set up dependencies between the RT resource and the Framebuffer.
mImage->addWriteDependency(contextVk, framebufferVk);
onImageViewGraphAccess(contextVk);
return angle::Result::Continue;
}
......@@ -147,9 +156,8 @@ vk::ImageHelper *RenderTargetVk::getImageForRead(ContextVk *contextVk,
// However, this needs context to be available here, or all call sites changed
// to perform the layout transition and set the dependency.
mImage->addWriteDependency(contextVk, readingResource);
mImage->changeLayout(mImage->getAspectFlags(), layout, commandBuffer);
onImageViewGraphAccess(contextVk);
return mImage;
}
......@@ -158,6 +166,7 @@ vk::ImageHelper *RenderTargetVk::getImageForWrite(ContextVk *contextVk,
{
ASSERT(mImage && mImage->valid());
mImage->addWriteDependency(contextVk, writingResource);
onImageViewGraphAccess(contextVk);
return mImage;
}
......@@ -173,4 +182,8 @@ angle::Result RenderTargetVk::flushStagedUpdates(ContextVk *contextVk)
mLayerIndex + 1, commandBuffer);
}
void RenderTargetVk::onImageViewGraphAccess(ContextVk *contextVk) const
{
mImageViews->onGraphAccess(contextVk->getCommandGraph());
}
} // namespace rx
......@@ -82,6 +82,8 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget
angle::Result flushStagedUpdates(ContextVk *contextVk);
void onImageViewGraphAccess(ContextVk *contextVk) const;
private:
vk::ImageHelper *mImage;
vk::ImageViewHelper *mImageViews;
......
......@@ -210,10 +210,10 @@ void RenderbufferVk::releaseAndDeleteImage(ContextVk *contextVk)
void RenderbufferVk::releaseImage(ContextVk *contextVk)
{
RendererVk *renderer = contextVk->getRenderer();
if (mImage && mOwnsImage)
{
RendererVk *renderer = contextVk->getRenderer();
mImage->releaseImage(renderer);
mImage->releaseStagingBuffer(renderer);
}
......@@ -222,7 +222,7 @@ void RenderbufferVk::releaseImage(ContextVk *contextVk)
mImage = nullptr;
}
mImageViews.release(contextVk);
mImageViews.release(renderer);
}
} // namespace rx
......@@ -170,7 +170,7 @@ class RendererVk : angle::NonCopyable
CollectGarbage(&sharedGarbage, garbageIn...);
if (!sharedGarbage.empty())
{
mSharedGarbage.emplace_back(std::move(*use), std::move(sharedGarbage));
collectGarbage(std::move(*use), std::move(sharedGarbage));
}
else
{
......@@ -181,6 +181,11 @@ class RendererVk : angle::NonCopyable
use->init();
}
void collectGarbage(vk::SharedResourceUse &&use, std::vector<vk::GarbageObject> &&sharedGarbage)
{
mSharedGarbage.emplace_back(std::move(use), std::move(sharedGarbage));
}
static constexpr size_t kMaxExtensionNames = 200;
using ExtensionNameList = angle::FixedVector<const char *, kMaxExtensionNames>;
......
......@@ -171,7 +171,11 @@ OffscreenSurfaceVk::OffscreenSurfaceVk(const egl::SurfaceState &surfaceState,
EGLint width,
EGLint height)
: SurfaceVk(surfaceState), mWidth(width), mHeight(height)
{}
{
mColorRenderTarget.init(&mColorAttachment.image, &mColorAttachment.imageViews, 0, 0);
mDepthStencilRenderTarget.init(&mDepthStencilAttachment.image,
&mDepthStencilAttachment.imageViews, 0, 0);
}
OffscreenSurfaceVk::~OffscreenSurfaceVk() {}
......@@ -399,7 +403,12 @@ WindowSurfaceVk::WindowSurfaceVk(const egl::SurfaceState &surfaceState,
mCompositeAlpha(VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR),
mCurrentSwapHistoryIndex(0),
mCurrentSwapchainImageIndex(0)
{}
{
// Initialize the color render target with the multisampled targets. If not multisampled, the
// render target will be updated to refer to a swapchain image on every acquire.
mColorRenderTarget.init(&mColorImageMS, &mColorImageMSViews, 0, 0);
mDepthStencilRenderTarget.init(&mDepthStencilImage, &mDepthStencilImageViews, 0, 0);
}
WindowSurfaceVk::~WindowSurfaceVk()
{
......@@ -871,14 +880,14 @@ void WindowSurfaceVk::releaseSwapchainImages(ContextVk *contextVk)
{
mDepthStencilImage.releaseImage(renderer);
mDepthStencilImage.releaseStagingBuffer(renderer);
mDepthStencilImageViews.release(contextVk);
mDepthStencilImageViews.release(renderer);
}
if (mColorImageMS.valid())
{
mColorImageMS.releaseImage(renderer);
mColorImageMS.releaseStagingBuffer(renderer);
mColorImageMSViews.release(contextVk);
mColorImageMSViews.release(renderer);
contextVk->addGarbage(&mFramebufferMS);
}
......@@ -888,7 +897,7 @@ void WindowSurfaceVk::releaseSwapchainImages(ContextVk *contextVk)
swapchainImage.image.resetImageWeakReference();
swapchainImage.image.destroy(contextVk->getDevice());
swapchainImage.imageViews.release(contextVk);
swapchainImage.imageViews.release(renderer);
contextVk->addGarbage(&swapchainImage.framebuffer);
// present history must have already been taken care of.
......
......@@ -403,6 +403,7 @@ angle::Result TextureVk::copySubImageImpl(const gl::Context *context,
const vk::ImageView *readImageView = nullptr;
ANGLE_TRY(colorReadRT->getImageView(contextVk, &readImageView));
colorReadRT->onImageViewGraphAccess(contextVk);
return copySubImageImplWithDraw(contextVk, offsetImageIndex, modifiedDestOffset, destFormat,
0, clippedSourceArea, isViewportFlipY, false, false, false,
......@@ -452,10 +453,10 @@ angle::Result TextureVk::copySubTextureImpl(ContextVk *contextVk,
// If it's possible to perform the copy with a draw call, do that.
if (CanCopyWithDraw(renderer, sourceVkFormat, destVkFormat) && !forceCPUPath)
{
return copySubImageImplWithDraw(contextVk, offsetImageIndex, destOffset, destVkFormat,
sourceLevel, sourceArea, false, unpackFlipY,
unpackPremultiplyAlpha, unpackUnmultiplyAlpha,
&source->getImage(), &source->getFetchImageView());
return copySubImageImplWithDraw(
contextVk, offsetImageIndex, destOffset, destVkFormat, sourceLevel, sourceArea, false,
unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha, &source->getImage(),
&source->getFetchImageViewAndRecordUse(contextVk));
}
if (sourceLevel != 0)
......@@ -1362,7 +1363,7 @@ angle::Result TextureVk::syncState(const gl::Context *context,
uint32_t layerCount =
mState.getType() == gl::TextureType::_2D ? 1 : mImage->getLayerCount();
mImageViews.release(contextVk);
mImageViews.release(contextVk->getRenderer());
const gl::ImageDesc &baseLevelDesc = mState.getBaseLevelDesc();
ANGLE_TRY(initImageViews(contextVk, mImage->getFormat(),
......@@ -1457,11 +1458,13 @@ void TextureVk::releaseOwnershipOfImage(const gl::Context *context)
releaseAndDeleteImage(contextVk);
}
const vk::ImageView &TextureVk::getReadImageView() const
const vk::ImageView &TextureVk::getReadImageViewAndRecordUse(ContextVk *contextVk) const
{
ASSERT(mImage->valid());
if (mState.isStencilMode() && mImageViews.getStencilReadImageView().valid())
mImageViews.onGraphAccess(contextVk->getCommandGraph());
if (mState.isStencilMode() && mImageViews.hasStencilReadImageView())
{
return mImageViews.getStencilReadImageView();
}
......@@ -1469,18 +1472,19 @@ const vk::ImageView &TextureVk::getReadImageView() const
return mImageViews.getReadImageView();
}
const vk::ImageView &TextureVk::getFetchImageView() const
const vk::ImageView &TextureVk::getFetchImageViewAndRecordUse(ContextVk *contextVk) const
{
ASSERT(mImage->valid());
mImageViews.onGraphAccess(contextVk->getCommandGraph());
// We don't currently support fetch for depth/stencil cube map textures.
ASSERT(!mImageViews.getStencilReadImageView().valid() ||
!mImageViews.getFetchImageView().valid());
return (mImageViews.getFetchImageView().valid() ? mImageViews.getFetchImageView()
: mImageViews.getReadImageView());
ASSERT(!mImageViews.hasStencilReadImageView() || !mImageViews.hasFetchImageView());
return (mImageViews.hasFetchImageView() ? mImageViews.getFetchImageView()
: mImageViews.getReadImageView());
}
angle::Result TextureVk::getLevelLayerImageView(vk::Context *context,
angle::Result TextureVk::getLevelLayerImageView(ContextVk *contextVk,
size_t level,
size_t layer,
const vk::ImageView **imageViewOut)
......@@ -1490,7 +1494,7 @@ angle::Result TextureVk::getLevelLayerImageView(vk::Context *context,
uint32_t nativeLevel = getNativeImageLevel(static_cast<uint32_t>(level));
uint32_t nativeLayer = getNativeImageLayer(static_cast<uint32_t>(layer));
return mImageViews.getLevelLayerDrawImageView(context, *mImage, nativeLevel, nativeLayer,
return mImageViews.getLevelLayerDrawImageView(contextVk, *mImage, nativeLevel, nativeLayer,
imageViewOut);
}
......@@ -1602,11 +1606,13 @@ angle::Result TextureVk::initImageViews(ContextVk *contextVk,
void TextureVk::releaseImage(ContextVk *contextVk)
{
RendererVk *renderer = contextVk->getRenderer();
if (mImage)
{
if (mOwnsImage)
{
mImage->releaseImage(contextVk->getRenderer());
mImage->releaseImage(renderer);
}
else
{
......@@ -1614,7 +1620,7 @@ void TextureVk::releaseImage(ContextVk *contextVk)
}
}
mImageViews.release(contextVk);
mImageViews.release(renderer);
for (RenderTargetVector &renderTargetLevels : mRenderTargets)
{
......
......@@ -152,12 +152,17 @@ class TextureVk : public TextureImpl
return *mImage;
}
void onImageViewGraphAccess(vk::CommandGraph *commandGraph)
{
mImageViews.onGraphAccess(commandGraph);
}
void releaseOwnershipOfImage(const gl::Context *context);
const vk::ImageView &getReadImageView() const;
const vk::ImageView &getReadImageViewAndRecordUse(ContextVk *contextVk) const;
// A special view for cube maps as a 2D array, used with shaders that do texelFetch() and for
// seamful cube map emulation.
const vk::ImageView &getFetchImageView() const;
const vk::ImageView &getFetchImageViewAndRecordUse(ContextVk *contextVk) const;
angle::Result getStorageImageView(ContextVk *contextVk,
bool allLayers,
size_t level,
......@@ -295,7 +300,7 @@ class TextureVk : public TextureImpl
uint32_t levelCount,
uint32_t layerCount);
angle::Result initRenderTargets(ContextVk *contextVk, GLuint layerCount, GLuint levelIndex);
angle::Result getLevelLayerImageView(vk::Context *context,
angle::Result getLevelLayerImageView(ContextVk *contextVk,
size_t level,
size_t layer,
const vk::ImageView **imageViewOut);
......
......@@ -2507,6 +2507,8 @@ angle::Result ImageHelper::stageSubresourceUpdateFromFramebuffer(
PackPixelsParams params(clippedRectangle, copyFormat, static_cast<GLuint>(outputRowPitch),
isViewportFlipEnabled, nullptr, 0);
RenderTargetVk *readRenderTarget = framebufferVk->getColorReadRenderTarget();
// 2- copy the source image region to the pixel buffer using a cpu readback
if (loadFunction.requiresConversion)
{
......@@ -2518,9 +2520,9 @@ angle::Result ImageHelper::stageSubresourceUpdateFromFramebuffer(
ANGLE_VK_CHECK_ALLOC(contextVk, context->getScratchBuffer(bufferSize, &memoryBuffer));
// Read into the scratch buffer
ANGLE_TRY(framebufferVk->readPixelsImpl(
contextVk, clippedRectangle, params, VK_IMAGE_ASPECT_COLOR_BIT,
framebufferVk->getColorReadRenderTarget(), memoryBuffer->data()));
ANGLE_TRY(framebufferVk->readPixelsImpl(contextVk, clippedRectangle, params,
VK_IMAGE_ASPECT_COLOR_BIT, readRenderTarget,
memoryBuffer->data()));
// Load from scratch buffer to our pixel buffer
loadFunction.loadFunction(clippedRectangle.width, clippedRectangle.height, 1,
......@@ -2530,9 +2532,9 @@ angle::Result ImageHelper::stageSubresourceUpdateFromFramebuffer(
else
{
// We read directly from the framebuffer into our pixel buffer.
ANGLE_TRY(framebufferVk->readPixelsImpl(
contextVk, clippedRectangle, params, VK_IMAGE_ASPECT_COLOR_BIT,
framebufferVk->getColorReadRenderTarget(), stagingPointer));
ANGLE_TRY(framebufferVk->readPixelsImpl(contextVk, clippedRectangle, params,
VK_IMAGE_ASPECT_COLOR_BIT, readRenderTarget,
stagingPointer));
}
// 3- enqueue the destination image subresource update
......@@ -2931,7 +2933,10 @@ void FramebufferHelper::release(ContextVk *contextVk)
}
// ImageViewHelper implementation.
ImageViewHelper::ImageViewHelper() = default;
ImageViewHelper::ImageViewHelper()
{
mUse.init();
}
ImageViewHelper::ImageViewHelper(ImageViewHelper &&other)
{
......@@ -2942,17 +2947,22 @@ ImageViewHelper::ImageViewHelper(ImageViewHelper &&other)
std::swap(mLayerLevelDrawImageViews, other.mLayerLevelDrawImageViews);
}
ImageViewHelper::~ImageViewHelper() = default;
ImageViewHelper::~ImageViewHelper()
{
mUse.release();
}
void ImageViewHelper::release(ContextVk *contextVk)
void ImageViewHelper::release(RendererVk *renderer)
{
contextVk->addGarbage(&mReadImageView);
contextVk->addGarbage(&mFetchImageView);
contextVk->addGarbage(&mStencilReadImageView);
std::vector<GarbageObject> garbage;
garbage.emplace_back(GetGarbage(&mReadImageView));
garbage.emplace_back(GetGarbage(&mFetchImageView));
garbage.emplace_back(GetGarbage(&mStencilReadImageView));
for (vk::ImageView &imageView : mLevelDrawImageViews)
{
contextVk->addGarbage(&imageView);
garbage.emplace_back(GetGarbage(&imageView));
}
mLevelDrawImageViews.clear();
......@@ -2960,10 +2970,15 @@ void ImageViewHelper::release(ContextVk *contextVk)
{
for (vk::ImageView &imageView : layerViews)
{
contextVk->addGarbage(&imageView);
garbage.emplace_back(GetGarbage(&imageView));
}
}
mLayerLevelDrawImageViews.clear();
renderer->collectGarbage(std::move(mUse), std::move(garbage));
// Ensure the resource use is always valid.
mUse.init();
}
void ImageViewHelper::destroy(VkDevice device)
......@@ -3036,6 +3051,8 @@ angle::Result ImageViewHelper::getLevelDrawImageView(ContextVk *contextVk,
uint32_t layer,
const ImageView **imageViewOut)
{
onGraphAccess(contextVk->getCommandGraph());
// TODO(http://anglebug.com/4008): Possibly incorrect level count.
ImageView *imageView = GetLevelImageView(&mLevelDrawImageViews, level, 1);
......@@ -3050,7 +3067,7 @@ angle::Result ImageViewHelper::getLevelDrawImageView(ContextVk *contextVk,
imageView, level, 1, layer, image.getLayerCount());
}
angle::Result ImageViewHelper::getLevelLayerDrawImageView(Context *context,
angle::Result ImageViewHelper::getLevelLayerDrawImageView(ContextVk *contextVk,
const ImageHelper &image,
uint32_t level,
uint32_t layer,
......@@ -3059,6 +3076,8 @@ angle::Result ImageViewHelper::getLevelLayerDrawImageView(Context *context,
ASSERT(image.valid());
ASSERT(!image.getFormat().actualImageFormat().isBlock);
onGraphAccess(contextVk->getCommandGraph());
uint32_t layerCount = GetImageLayerCountForView(image);
// Lazily allocate the storage for image views
......@@ -3081,7 +3100,7 @@ angle::Result ImageViewHelper::getLevelLayerDrawImageView(Context *context,
// Note that these views are specifically made to be used as color attachments, and therefore
// don't have swizzle.
gl::TextureType viewType = vk::Get2DTextureType(1, image.getSamples());
return image.initLayerImageView(context, viewType, image.getAspectFlags(), gl::SwizzleState(),
return image.initLayerImageView(contextVk, viewType, image.getAspectFlags(), gl::SwizzleState(),
imageView, level, 1, layer, 1);
}
......
......@@ -997,13 +997,21 @@ class ImageViewHelper : angle::NonCopyable
ImageViewHelper(ImageViewHelper &&other);
~ImageViewHelper();
void release(ContextVk *contextVk);
void release(RendererVk *renderer);
void destroy(VkDevice device);
const ImageView &getReadImageView() const { return mReadImageView; }
const ImageView &getFetchImageView() const { return mFetchImageView; }
const ImageView &getStencilReadImageView() const { return mStencilReadImageView; }
// Used when initialized RenderTargets.
bool hasStencilReadImageView() const { return mStencilReadImageView.valid(); }
bool hasFetchImageView() const { return mFetchImageView.valid(); }
// Store reference to usage in graph.
void onGraphAccess(CommandGraph *commandGraph) const { commandGraph->onResourceUse(mUse); }
// Creates views with multiple layers and levels.
angle::Result initReadViews(ContextVk *contextVk,
gl::TextureType viewType,
......@@ -1024,13 +1032,16 @@ class ImageViewHelper : angle::NonCopyable
const ImageView **imageViewOut);
// Creates a view with a single layer of the level.
angle::Result getLevelLayerDrawImageView(Context *context,
angle::Result getLevelLayerDrawImageView(ContextVk *contextVk,
const ImageHelper &image,
uint32_t level,
uint32_t layer,
const ImageView **imageViewOut);
private:
// Lifetime.
SharedResourceUse mUse;
// Read views.
ImageView mReadImageView;
ImageView mFetchImageView;
......
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