Commit 1c1c6b4e by Ian Elliott Committed by Commit Bot

Vulkan: Cache/re-use vkImageView's per max level

For applications that frequently switch a texture's max level, cache and re-use "read view" vkImageViews per max-level. Test: NBA 2K20 Test: angle_deqp_gles3_tests --gtest_filter=dEQP.GLES3/functional_texture_mipmap_*_max_level_* --use-angle=vulkan Bug: b/161993151 Change-Id: I9a6a81d5234196040bc6c264ec627a073ba73293 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2321370 Commit-Queue: Ian Elliott <ianelliott@google.com> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org>
parent 4cf2501c
......@@ -123,13 +123,11 @@ angle::Result RenderTargetVk::getAndRetainCopyImageView(ContextVk *contextVk,
retainImageViews(contextVk);
const vk::ImageViewHelper *imageViews = mImageViews;
const vk::ImageView &copyView = imageViews->getCopyImageView();
// If the source of render target is a texture or renderbuffer, this will always be valid. This
// is also where 3D or 2DArray images could be the source of the render target.
if (copyView.valid())
if (imageViews->hasCopyImageView())
{
*imageViewOut = &copyView;
*imageViewOut = &imageViews->getCopyImageView();
return angle::Result::Continue;
}
......
......@@ -1688,20 +1688,17 @@ angle::Result TextureVk::updateBaseMaxLevels(ContextVk *contextVk,
// number of mip levels
if (!baseLevelChanged && (maxLevel < baseLevel + mImage->getLevelCount()))
{
// Don't need to respecify the texture; just redo the texture's vkImageViews
// Don't need to respecify the texture; but do need to update which vkImageView's are
// served up by ImageViewHelper
ASSERT(maxLevelChanged);
// Release the current vkImageViews
RendererVk *renderer = contextVk->getRenderer();
mImageViews.release(renderer);
// Track the levels in our ImageHelper
mImage->setBaseAndMaxLevels(baseLevel, maxLevel);
// Update the texture's serial so that the descriptor set is updated correctly
mSerial = contextVk->generateTextureSerial();
// Change the vkImageViews
// Update the current max level in ImageViewHelper
const gl::ImageDesc &baseLevelDesc = mState.getBaseLevelDesc();
// We use a special layer count here to handle EGLImages. They might only be
// looking at one layer of a cube or 2D array texture.
......@@ -2243,15 +2240,9 @@ angle::Result TextureVk::initImageViews(ContextVk *contextVk,
gl::SwizzleState readSwizzle = ApplySwizzle(formatSwizzle, mState.getSwizzleState());
ANGLE_TRY(mImageViews.initReadViews(contextVk, mState.getType(), *mImage, format, formatSwizzle,
readSwizzle, baseLevel, levelCount, baseLayer, layerCount));
if (mRequiresSRGBViews)
{
ASSERT((mImageCreateFlags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) != 0);
ANGLE_TRY(mImageViews.initSRGBReadViews(
contextVk, mState.getType(), *mImage, format, formatSwizzle, readSwizzle, baseLevel,
levelCount, baseLayer, layerCount, mImageUsageFlags & ~VK_IMAGE_USAGE_STORAGE_BIT));
}
readSwizzle, baseLevel, levelCount, baseLayer, layerCount,
mRequiresSRGBViews,
mImageUsageFlags & ~VK_IMAGE_USAGE_STORAGE_BIT));
return angle::Result::Continue;
}
......
......@@ -1583,38 +1583,93 @@ class ImageViewHelper : angle::NonCopyable
void release(RendererVk *renderer);
void destroy(VkDevice device);
const ImageView &getLinearReadImageView() const { return mLinearReadImageView; }
const ImageView &getNonLinearReadImageView() const { return mNonLinearReadImageView; }
const ImageView &getLinearFetchImageView() const { return mLinearFetchImageView; }
const ImageView &getNonLinearFetchImageView() const { return mNonLinearFetchImageView; }
const ImageView &getLinearCopyImageView() const { return mLinearCopyImageView; }
const ImageView &getNonLinearCopyImageView() const { return mNonLinearCopyImageView; }
const ImageView &getStencilReadImageView() const { return mStencilReadImageView; }
const ImageView &getLinearReadImageView() const
{
return getValidReadViewImpl(mPerLevelLinearReadImageViews);
}
const ImageView &getNonLinearReadImageView() const
{
return getValidReadViewImpl(mPerLevelNonLinearReadImageViews);
}
const ImageView &getLinearFetchImageView() const
{
return getValidReadViewImpl(mPerLevelLinearFetchImageViews);
}
const ImageView &getNonLinearFetchImageView() const
{
return getValidReadViewImpl(mPerLevelNonLinearFetchImageViews);
}
const ImageView &getLinearCopyImageView() const
{
return getValidReadViewImpl(mPerLevelLinearCopyImageViews);
}
const ImageView &getNonLinearCopyImageView() const
{
return getValidReadViewImpl(mPerLevelNonLinearCopyImageViews);
}
const ImageView &getStencilReadImageView() const
{
return getValidReadViewImpl(mPerLevelStencilReadImageViews);
}
const ImageView &getReadImageView() const
{
return mLinearColorspace ? mLinearReadImageView : mNonLinearReadImageView;
return mLinearColorspace ? getReadViewImpl(mPerLevelLinearReadImageViews)
: getReadViewImpl(mPerLevelNonLinearReadImageViews);
}
const ImageView &getFetchImageView() const
{
return mLinearColorspace ? mLinearFetchImageView : mNonLinearFetchImageView;
return mLinearColorspace ? getReadViewImpl(mPerLevelLinearFetchImageViews)
: getReadViewImpl(mPerLevelNonLinearFetchImageViews);
}
const ImageView &getCopyImageView() const
{
return mLinearColorspace ? mLinearCopyImageView : mNonLinearCopyImageView;
return mLinearColorspace ? getReadViewImpl(mPerLevelLinearCopyImageViews)
: getReadViewImpl(mPerLevelNonLinearCopyImageViews);
}
// Used when initialized RenderTargets.
bool hasStencilReadImageView() const { return mStencilReadImageView.valid(); }
bool hasStencilReadImageView() const
{
return (mCurrentMaxLevel < mPerLevelStencilReadImageViews.size())
? mPerLevelStencilReadImageViews[mCurrentMaxLevel].valid()
: false;
}
bool hasFetchImageView() const { return getFetchImageView().valid(); }
bool hasFetchImageView() const
{
if ((mLinearColorspace && (mCurrentMaxLevel < mPerLevelLinearFetchImageViews.size())) ||
(!mLinearColorspace && (mCurrentMaxLevel < mPerLevelNonLinearFetchImageViews.size())))
{
return getFetchImageView().valid();
}
else
{
return false;
}
}
bool hasCopyImageView() const
{
if ((mLinearColorspace && (mCurrentMaxLevel < mPerLevelLinearCopyImageViews.size())) ||
(!mLinearColorspace && (mCurrentMaxLevel < mPerLevelNonLinearCopyImageViews.size())))
{
return getFetchImageView().valid();
}
else
{
return false;
}
}
// Store reference to usage in graph.
void retain(ResourceUseList *resourceUseList) const { resourceUseList->add(mUse); }
// Creates views with multiple layers and levels.
// For applications that frequently switch a texture's max level, and make no other changes to
// the texture, change the currently-used max level, and potentially create new "read views"
// for the new max-level
angle::Result initReadViews(ContextVk *contextVk,
gl::TextureType viewType,
const ImageHelper &image,
......@@ -1624,19 +1679,8 @@ class ImageViewHelper : angle::NonCopyable
uint32_t baseLevel,
uint32_t levelCount,
uint32_t baseLayer,
uint32_t layerCount);
// Create SRGB-reinterpreted read views
angle::Result initSRGBReadViews(ContextVk *contextVk,
gl::TextureType viewType,
const ImageHelper &image,
const Format &format,
const gl::SwizzleState &formatSwizzle,
const gl::SwizzleState &readSwizzle,
uint32_t baseLevel,
uint32_t levelCount,
uint32_t baseLayer,
uint32_t layerCount,
bool requiresSRGBViews,
VkImageUsageFlags imageUsageFlags);
// Creates a view with all layers of the level.
......@@ -1662,28 +1706,83 @@ class ImageViewHelper : angle::NonCopyable
private:
ImageView &getReadImageView()
{
return mLinearColorspace ? mLinearReadImageView : mNonLinearReadImageView;
return mLinearColorspace ? getReadViewImpl(mPerLevelLinearReadImageViews)
: getReadViewImpl(mPerLevelNonLinearReadImageViews);
}
ImageView &getFetchImageView()
{
return mLinearColorspace ? mLinearFetchImageView : mNonLinearFetchImageView;
return mLinearColorspace ? getReadViewImpl(mPerLevelLinearFetchImageViews)
: getReadViewImpl(mPerLevelNonLinearFetchImageViews);
}
ImageView &getCopyImageView()
{
return mLinearColorspace ? mLinearCopyImageView : mNonLinearCopyImageView;
return mLinearColorspace ? getReadViewImpl(mPerLevelLinearCopyImageViews)
: getReadViewImpl(mPerLevelNonLinearCopyImageViews);
}
// Used by public get*ImageView() methods to do proper assert based on vector size and validity
inline const ImageView &getValidReadViewImpl(const ImageViewVector &imageViewVector) const
{
ASSERT(mCurrentMaxLevel < imageViewVector.size() &&
imageViewVector[mCurrentMaxLevel].valid());
return imageViewVector[mCurrentMaxLevel];
}
// Used by public get*ImageView() methods to do proper assert based on vector size
inline const ImageView &getReadViewImpl(const ImageViewVector &imageViewVector) const
{
ASSERT(mCurrentMaxLevel < imageViewVector.size());
return imageViewVector[mCurrentMaxLevel];
}
// Used by private get*ImageView() methods to do proper assert based on vector size
inline ImageView &getReadViewImpl(ImageViewVector &imageViewVector)
{
ASSERT(mCurrentMaxLevel < imageViewVector.size());
return imageViewVector[mCurrentMaxLevel];
}
// Creates views with multiple layers and levels.
angle::Result initReadViewsImpl(ContextVk *contextVk,
gl::TextureType viewType,
const ImageHelper &image,
const Format &format,
const gl::SwizzleState &formatSwizzle,
const gl::SwizzleState &readSwizzle,
uint32_t baseLevel,
uint32_t levelCount,
uint32_t baseLayer,
uint32_t layerCount);
// Create SRGB-reinterpreted read views
angle::Result initSRGBReadViewsImpl(ContextVk *contextVk,
gl::TextureType viewType,
const ImageHelper &image,
const Format &format,
const gl::SwizzleState &formatSwizzle,
const gl::SwizzleState &readSwizzle,
uint32_t baseLevel,
uint32_t levelCount,
uint32_t baseLayer,
uint32_t layerCount,
VkImageUsageFlags imageUsageFlags);
// Lifetime.
SharedResourceUse mUse;
// Read views
ImageView mLinearReadImageView;
ImageView mNonLinearReadImageView;
ImageView mLinearFetchImageView;
ImageView mNonLinearFetchImageView;
ImageView mLinearCopyImageView;
ImageView mNonLinearCopyImageView;
ImageView mStencilReadImageView;
// For applications that frequently switch a texture's max level, and make no other changes to
// the texture, keep track of the currently-used max level, and keep one "read view" per
// max-level
uint32_t mCurrentMaxLevel;
// Read views (one per max-level)
ImageViewVector mPerLevelLinearReadImageViews;
ImageViewVector mPerLevelNonLinearReadImageViews;
ImageViewVector mPerLevelLinearFetchImageViews;
ImageViewVector mPerLevelNonLinearFetchImageViews;
ImageViewVector mPerLevelLinearCopyImageViews;
ImageViewVector mPerLevelNonLinearCopyImageViews;
ImageViewVector mPerLevelStencilReadImageViews;
bool mLinearColorspace;
......
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