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, ...@@ -123,13 +123,11 @@ angle::Result RenderTargetVk::getAndRetainCopyImageView(ContextVk *contextVk,
retainImageViews(contextVk); retainImageViews(contextVk);
const vk::ImageViewHelper *imageViews = mImageViews; 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 // 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. // 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; return angle::Result::Continue;
} }
......
...@@ -1688,20 +1688,17 @@ angle::Result TextureVk::updateBaseMaxLevels(ContextVk *contextVk, ...@@ -1688,20 +1688,17 @@ angle::Result TextureVk::updateBaseMaxLevels(ContextVk *contextVk,
// number of mip levels // number of mip levels
if (!baseLevelChanged && (maxLevel < baseLevel + mImage->getLevelCount())) 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); ASSERT(maxLevelChanged);
// Release the current vkImageViews
RendererVk *renderer = contextVk->getRenderer();
mImageViews.release(renderer);
// Track the levels in our ImageHelper // Track the levels in our ImageHelper
mImage->setBaseAndMaxLevels(baseLevel, maxLevel); mImage->setBaseAndMaxLevels(baseLevel, maxLevel);
// Update the texture's serial so that the descriptor set is updated correctly // Update the texture's serial so that the descriptor set is updated correctly
mSerial = contextVk->generateTextureSerial(); mSerial = contextVk->generateTextureSerial();
// Change the vkImageViews // Update the current max level in ImageViewHelper
const gl::ImageDesc &baseLevelDesc = mState.getBaseLevelDesc(); const gl::ImageDesc &baseLevelDesc = mState.getBaseLevelDesc();
// We use a special layer count here to handle EGLImages. They might only be // 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. // looking at one layer of a cube or 2D array texture.
...@@ -2243,15 +2240,9 @@ angle::Result TextureVk::initImageViews(ContextVk *contextVk, ...@@ -2243,15 +2240,9 @@ angle::Result TextureVk::initImageViews(ContextVk *contextVk,
gl::SwizzleState readSwizzle = ApplySwizzle(formatSwizzle, mState.getSwizzleState()); gl::SwizzleState readSwizzle = ApplySwizzle(formatSwizzle, mState.getSwizzleState());
ANGLE_TRY(mImageViews.initReadViews(contextVk, mState.getType(), *mImage, format, formatSwizzle, ANGLE_TRY(mImageViews.initReadViews(contextVk, mState.getType(), *mImage, format, formatSwizzle,
readSwizzle, baseLevel, levelCount, baseLayer, layerCount)); readSwizzle, baseLevel, levelCount, baseLayer, layerCount,
mRequiresSRGBViews,
if (mRequiresSRGBViews) mImageUsageFlags & ~VK_IMAGE_USAGE_STORAGE_BIT));
{
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));
}
return angle::Result::Continue; return angle::Result::Continue;
} }
......
...@@ -1583,38 +1583,93 @@ class ImageViewHelper : angle::NonCopyable ...@@ -1583,38 +1583,93 @@ class ImageViewHelper : angle::NonCopyable
void release(RendererVk *renderer); void release(RendererVk *renderer);
void destroy(VkDevice device); void destroy(VkDevice device);
const ImageView &getLinearReadImageView() const { return mLinearReadImageView; } const ImageView &getLinearReadImageView() const
const ImageView &getNonLinearReadImageView() const { return mNonLinearReadImageView; } {
const ImageView &getLinearFetchImageView() const { return mLinearFetchImageView; } return getValidReadViewImpl(mPerLevelLinearReadImageViews);
const ImageView &getNonLinearFetchImageView() const { return mNonLinearFetchImageView; } }
const ImageView &getLinearCopyImageView() const { return mLinearCopyImageView; } const ImageView &getNonLinearReadImageView() const
const ImageView &getNonLinearCopyImageView() const { return mNonLinearCopyImageView; } {
const ImageView &getStencilReadImageView() const { return mStencilReadImageView; } 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 const ImageView &getReadImageView() const
{ {
return mLinearColorspace ? mLinearReadImageView : mNonLinearReadImageView; return mLinearColorspace ? getReadViewImpl(mPerLevelLinearReadImageViews)
: getReadViewImpl(mPerLevelNonLinearReadImageViews);
} }
const ImageView &getFetchImageView() const const ImageView &getFetchImageView() const
{ {
return mLinearColorspace ? mLinearFetchImageView : mNonLinearFetchImageView; return mLinearColorspace ? getReadViewImpl(mPerLevelLinearFetchImageViews)
: getReadViewImpl(mPerLevelNonLinearFetchImageViews);
} }
const ImageView &getCopyImageView() const const ImageView &getCopyImageView() const
{ {
return mLinearColorspace ? mLinearCopyImageView : mNonLinearCopyImageView; return mLinearColorspace ? getReadViewImpl(mPerLevelLinearCopyImageViews)
: getReadViewImpl(mPerLevelNonLinearCopyImageViews);
} }
// Used when initialized RenderTargets. // 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. // Store reference to usage in graph.
void retain(ResourceUseList *resourceUseList) const { resourceUseList->add(mUse); } 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, angle::Result initReadViews(ContextVk *contextVk,
gl::TextureType viewType, gl::TextureType viewType,
const ImageHelper &image, const ImageHelper &image,
...@@ -1624,19 +1679,8 @@ class ImageViewHelper : angle::NonCopyable ...@@ -1624,19 +1679,8 @@ class ImageViewHelper : angle::NonCopyable
uint32_t baseLevel, uint32_t baseLevel,
uint32_t levelCount, uint32_t levelCount,
uint32_t baseLayer, 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, uint32_t layerCount,
bool requiresSRGBViews,
VkImageUsageFlags imageUsageFlags); VkImageUsageFlags imageUsageFlags);
// Creates a view with all layers of the level. // Creates a view with all layers of the level.
...@@ -1662,28 +1706,83 @@ class ImageViewHelper : angle::NonCopyable ...@@ -1662,28 +1706,83 @@ class ImageViewHelper : angle::NonCopyable
private: private:
ImageView &getReadImageView() ImageView &getReadImageView()
{ {
return mLinearColorspace ? mLinearReadImageView : mNonLinearReadImageView; return mLinearColorspace ? getReadViewImpl(mPerLevelLinearReadImageViews)
: getReadViewImpl(mPerLevelNonLinearReadImageViews);
} }
ImageView &getFetchImageView() ImageView &getFetchImageView()
{ {
return mLinearColorspace ? mLinearFetchImageView : mNonLinearFetchImageView; return mLinearColorspace ? getReadViewImpl(mPerLevelLinearFetchImageViews)
: getReadViewImpl(mPerLevelNonLinearFetchImageViews);
} }
ImageView &getCopyImageView() 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. // Lifetime.
SharedResourceUse mUse; SharedResourceUse mUse;
// Read views // For applications that frequently switch a texture's max level, and make no other changes to
ImageView mLinearReadImageView; // the texture, keep track of the currently-used max level, and keep one "read view" per
ImageView mNonLinearReadImageView; // max-level
ImageView mLinearFetchImageView; uint32_t mCurrentMaxLevel;
ImageView mNonLinearFetchImageView;
ImageView mLinearCopyImageView; // Read views (one per max-level)
ImageView mNonLinearCopyImageView; ImageViewVector mPerLevelLinearReadImageViews;
ImageView mStencilReadImageView; ImageViewVector mPerLevelNonLinearReadImageViews;
ImageViewVector mPerLevelLinearFetchImageViews;
ImageViewVector mPerLevelNonLinearFetchImageViews;
ImageViewVector mPerLevelLinearCopyImageViews;
ImageViewVector mPerLevelNonLinearCopyImageViews;
ImageViewVector mPerLevelStencilReadImageViews;
bool mLinearColorspace; 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