Commit afd32d8e by Charlie Lao Committed by Commit Bot

Vulkan: Remove mMaxLevel from ImageHelper class

This CL removes mMaxLevel from ImageHelper class. Instead, it now uses front end's max level information when possible. Bug: b/181800403 Change-Id: Ie0f6bd11e3ca0d4ddfc98f21261396c4d71b7140 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2796153 Commit-Queue: Charlie Lao <cclao@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarIan Elliott <ianelliott@google.com>
parent 4756d5e6
......@@ -1747,15 +1747,16 @@ angle::Result TextureVk::generateMipmapsWithCompute(ContextVk *contextVk)
// If the image has more levels than supported, generate as many mips as possible at a time.
const vk::LevelIndex maxGenerateLevels(UtilsVk::GetGenerateMipmapMaxLevels(contextVk));
vk::LevelIndex destMaxLevelVk = mImage->toVkLevel(gl::LevelIndex(mState.getMipmapMaxLevel()));
for (vk::LevelIndex destBaseLevelVk =
mImage->toVkLevel(gl::LevelIndex(mState.getEffectiveBaseLevel() + 1));
destBaseLevelVk < vk::LevelIndex(mImage->getLevelCount());
destBaseLevelVk <= destMaxLevelVk;
destBaseLevelVk = destBaseLevelVk + maxGenerateLevels.get())
{
vk::CommandBufferAccess access;
uint32_t writeLevelCount =
std::min(maxGenerateLevels.get(), mImage->getLevelCount() - destBaseLevelVk.get());
std::min(maxGenerateLevels.get(), destMaxLevelVk.get() + 1 - destBaseLevelVk.get());
access.onImageComputeShaderWrite(mImage->toGLLevel(destBaseLevelVk), writeLevelCount, 0,
mImage->getLayerCount(), VK_IMAGE_ASPECT_COLOR_BIT,
mImage);
......@@ -1781,7 +1782,7 @@ angle::Result TextureVk::generateMipmapsWithCompute(ContextVk *contextVk)
vk::LevelIndex destLevelVk = destBaseLevelVk + levelVk.get();
// If fewer levels left than maxGenerateLevels, cut the loop short.
if (destLevelVk >= vk::LevelIndex(mImage->getLevelCount()))
if (destLevelVk > destMaxLevelVk)
{
destLevelCount = levelVk;
break;
......@@ -1925,7 +1926,6 @@ angle::Result TextureVk::updateBaseMaxLevels(ContextVk *contextVk,
{
mImage->setFirstAllocatedLevel(baseLevel);
}
mImage->setMaxLevel(maxLevel);
// No further work to do, let staged updates handle the new levels
return angle::Result::Continue;
......@@ -1939,7 +1939,7 @@ angle::Result TextureVk::updateBaseMaxLevels(ContextVk *contextVk,
ASSERT(!baseLevelChanged || baseLevel >= mImage->getFirstAllocatedLevel());
ASSERT(!maxLevelChanged || maxLevel < gl::LevelIndex(mImage->getLevelCount()));
}
else if (!baseLevelChanged && (maxLevel < baseLevel + mImage->getLevelCount()))
else if (!baseLevelChanged && (maxLevel <= mImage->getLastAllocatedLevel()))
{
// With a valid image, check if only changing the maxLevel to a subset of the texture's
// actual number of mip levels
......@@ -1955,9 +1955,6 @@ angle::Result TextureVk::updateBaseMaxLevels(ContextVk *contextVk,
// Don't need to respecify the texture; but do need to update which vkImageView's are
// served up by ImageViewHelper
// Track the levels in our ImageHelper
mImage->setMaxLevel(maxLevel);
// 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
......@@ -2026,7 +2023,7 @@ angle::Result TextureVk::respecifyImageStorageAndLevels(ContextVk *contextVk,
{
ASSERT((mImage->getFirstAllocatedLevel() == gl::LevelIndex(0)) ||
(mImage->getFirstAllocatedLevel() == baseLevel));
ASSERT((mImage->getMaxLevel() == gl::LevelIndex(0)) || (mImage->getMaxLevel() == maxLevel));
ASSERT(!mState.getImmutableFormat());
releaseImage(contextVk);
return angle::Result::Continue;
}
......@@ -2074,10 +2071,6 @@ angle::Result TextureVk::respecifyImageStorageAndLevels(ContextVk *contextVk,
dstImage = mImage;
}
// After flushing prior staged updates, track the new levels (they are used in the flush, hence
// the wait)
dstImage->setMaxLevel(maxLevel);
// Transfer the entire contents of the source image into the destination image.
ANGLE_TRY(copyAndStageImageData(contextVk, previousFirstAllocateLevel, srcImage, dstImage));
......
......@@ -3636,7 +3636,6 @@ ImageHelper::ImageHelper(ImageHelper &&other)
mYuvConversionSampler(std::move(other.mYuvConversionSampler)),
mExternalFormat(other.mExternalFormat),
mFirstAllocatedLevel(other.mFirstAllocatedLevel),
mMaxLevel(other.mMaxLevel),
mLayerCount(other.mLayerCount),
mLevelCount(other.mLevelCount),
mStagingBuffer(std::move(other.mStagingBuffer)),
......@@ -3670,7 +3669,6 @@ void ImageHelper::resetCachedProperties()
mLastNonShaderReadOnlyLayout = ImageLayout::Undefined;
mCurrentShaderReadStageMask = 0;
mFirstAllocatedLevel = gl::LevelIndex(0);
mMaxLevel = gl::LevelIndex(0);
mLayerCount = 0;
mLevelCount = 0;
mExternalFormat = 0;
......@@ -3838,7 +3836,6 @@ angle::Result ImageHelper::initExternal(Context *context,
mSamples = std::max(samples, 1);
mImageSerial = context->getRenderer()->getResourceSerialFactory().generateImageSerial();
mFirstAllocatedLevel = immutable ? gl::LevelIndex(0) : baseLevel;
mMaxLevel = maxLevel;
mLevelCount = mipLevels;
mLayerCount = layerCount;
mUsage = usage;
......@@ -4382,12 +4379,12 @@ angle::Result ImageHelper::initImplicitMultisampledRenderToTexture(
: VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
constexpr VkImageCreateFlags kMultisampledCreateFlags = 0;
ANGLE_TRY(initExternal(context, textureType, resolveImage.getExtents(),
resolveImage.getFormat(), samples, kMultisampledUsageFlags,
kMultisampledCreateFlags, ImageLayout::Undefined, nullptr,
resolveImage.getFirstAllocatedLevel(), resolveImage.getMaxLevel(),
resolveImage.getLevelCount(), resolveImage.getLayerCount(),
isRobustResourceInitEnabled, false, nullptr));
ANGLE_TRY(
initExternal(context, textureType, resolveImage.getExtents(), resolveImage.getFormat(),
samples, kMultisampledUsageFlags, kMultisampledCreateFlags,
ImageLayout::Undefined, nullptr, resolveImage.getFirstAllocatedLevel(),
resolveImage.getLastAllocatedLevel(), resolveImage.getLevelCount(),
resolveImage.getLayerCount(), isRobustResourceInitEnabled, false, nullptr));
const VkMemoryPropertyFlags kMultisampledMemoryFlags =
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
......@@ -4399,7 +4396,7 @@ angle::Result ImageHelper::initImplicitMultisampledRenderToTexture(
// Remove the emulated format clear from the multisampled image if any. There is one already
// staged on the resolve image if needed.
removeStagedUpdates(context, getFirstAllocatedLevel(), getMaxLevel());
removeStagedUpdates(context, getFirstAllocatedLevel(), getLastAllocatedLevel());
return angle::Result::Continue;
}
......@@ -4571,11 +4568,6 @@ void ImageHelper::setFirstAllocatedLevel(gl::LevelIndex firstLevel)
mFirstAllocatedLevel = firstLevel;
}
void ImageHelper::setMaxLevel(gl::LevelIndex maxLevel)
{
mMaxLevel = maxLevel;
}
LevelIndex ImageHelper::toVkLevel(gl::LevelIndex levelIndexGL) const
{
return gl_vk::GetLevelIndex(levelIndexGL, mFirstAllocatedLevel);
......@@ -5984,9 +5976,6 @@ angle::Result ImageHelper::flushStagedUpdates(ContextVk *contextVk,
uint32_t updateBaseLayer, updateLayerCount;
update.getDestSubresource(mLayerCount, &updateBaseLayer, &updateLayerCount);
// If the update level is not within the requested range, skip the update.
const bool isUpdateLevelOutsideRange = updateMipLevelGL > mMaxLevel;
// If the update layers don't intersect the requested layers, skip the update.
const bool areUpdateLayersOutsideRange =
updateBaseLayer + updateLayerCount <= layerStart || updateBaseLayer >= layerEnd;
......@@ -5997,8 +5986,7 @@ angle::Result ImageHelper::flushStagedUpdates(ContextVk *contextVk,
// them. This can happen when recreating an image that has been partially incompatibly
// redefined, in which case only updates to the levels that haven't been redefined
// should be flushed.
if (isUpdateLevelOutsideRange || areUpdateLayersOutsideRange ||
skipLevelsMask.test(updateMipLevelVk.get()))
if (areUpdateLayersOutsideRange || skipLevelsMask.test(updateMipLevelVk.get()))
{
updatesToKeep.emplace_back(std::move(update));
continue;
......@@ -6152,9 +6140,14 @@ bool ImageHelper::hasStagedUpdatesForSubresource(gl::LevelIndex levelGL,
return false;
}
gl::LevelIndex ImageHelper::getLastAllocatedLevel() const
{
return mFirstAllocatedLevel + mLevelCount - 1;
}
bool ImageHelper::hasStagedUpdatesInAllocatedLevels() const
{
return hasStagedUpdatesInLevels(mFirstAllocatedLevel, mMaxLevel + 1);
return hasStagedUpdatesInLevels(mFirstAllocatedLevel, getLastAllocatedLevel() + 1);
}
bool ImageHelper::hasStagedUpdatesInLevels(gl::LevelIndex levelStart, gl::LevelIndex levelEnd) const
......@@ -6263,17 +6256,16 @@ void ImageHelper::removeSupersededUpdates(ContextVk *contextVk, gl::TexLevelMask
return false;
};
for (gl::LevelIndex level = mFirstAllocatedLevel; level <= mMaxLevel; ++level)
for (LevelIndex levelVk(0); levelVk < LevelIndex(mLevelCount); ++levelVk)
{
std::vector<SubresourceUpdate> *levelUpdates = getLevelUpdates(level);
gl::LevelIndex levelGL = toGLLevel(levelVk);
std::vector<SubresourceUpdate> *levelUpdates = getLevelUpdates(levelGL);
if (levelUpdates == nullptr)
{
ASSERT(static_cast<size_t>(level.get()) >= mSubresourceUpdates.size());
ASSERT(static_cast<size_t>(levelGL.get()) >= mSubresourceUpdates.size());
break;
}
LevelIndex levelVk = toVkLevel(level);
// If level is skipped (because incompatibly redefined), don't remove any of its updates.
if (skipLevelsMask.test(levelVk.get()))
{
......
......@@ -1795,8 +1795,7 @@ class ImageHelper final : public Resource, public angle::Subject
gl::LevelIndex getFirstAllocatedLevel() const { return mFirstAllocatedLevel; }
void setFirstAllocatedLevel(gl::LevelIndex firstLevel);
void setMaxLevel(gl::LevelIndex maxLevel);
gl::LevelIndex getMaxLevel() const { return mMaxLevel; }
gl::LevelIndex getLastAllocatedLevel() const;
LevelIndex toVkLevel(gl::LevelIndex levelIndexGL) const;
gl::LevelIndex toGLLevel(LevelIndex levelIndexVk) const;
......@@ -2070,7 +2069,6 @@ class ImageHelper final : public Resource, public angle::Subject
gl::LevelIndex mFirstAllocatedLevel;
// Cached properties.
gl::LevelIndex mMaxLevel;
uint32_t mLayerCount;
uint32_t mLevelCount;
......
......@@ -2708,7 +2708,7 @@ TEST_P(FramebufferTest_ES3, RenderAndInvalidateImmutableTextureWithBellowBaseLev
TEST_P(FramebufferTest_ES3, RenderImmutableTextureWithSubImageWithBeyondMaxLevel)
{
// ToDo: https://issuetracker.google.com/181800403
ANGLE_SKIP_TEST_IF(IsVulkan() || IsMetal());
ANGLE_SKIP_TEST_IF(IsMetal());
// Set up program to sample from specific lod level.
GLProgram textureLodProgram;
......
......@@ -3977,6 +3977,59 @@ TEST_P(Texture2DBaseMaxTestES3, RedefineMutableToImmutable)
}
}
// Test that redefine a level with incompatible size beyond the max level.
TEST_P(Texture2DBaseMaxTestES3, RedefineIncompatibleLevelBeyondMaxLevel)
{
initTest(false);
// Test that all mips have the expected data initially (this makes sure the texture image is
// created already).
for (uint32_t lod = 0; lod < kMipCount; ++lod)
{
setLodUniform(lod);
drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
}
uint32_t maxLevel = 1;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, maxLevel);
// Update level 0
const GLColor kNewMipLevle0Color = GLColor::yellow;
std::array<GLColor, getMipDataSize(kMip0Size, 0)> newMipData;
std::fill(newMipData.begin(), newMipData.end(), kNewMipLevle0Color);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kMip0Size, kMip0Size, GL_RGBA, GL_UNSIGNED_BYTE,
newMipData.data());
// Update level 2 with incompatible data
glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE,
newMipData.data());
EXPECT_GL_NO_ERROR();
// Test that the texture looks as expected.
const int w = getWindowWidth() - 1;
const int h = getWindowHeight() - 1;
for (uint32_t lod = 0; lod < maxLevel; ++lod)
{
setLodUniform(lod);
drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
if (lod == 0)
{
EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipLevle0Color);
EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipLevle0Color);
EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipLevle0Color);
EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipLevle0Color);
}
else
{
EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[lod]);
EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[lod]);
EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[lod]);
}
}
}
// Test to check that texture completeness is determined correctly when the texture base level is
// greater than 0, and also that level 0 is not sampled when base level is greater than 0.
TEST_P(Texture2DTestES3, DrawWithBaseLevel1)
......
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