Commit 08b7c55c by Charlie Lao Committed by Commit Bot

Vulkan: Remove mBaseLevel from ImageHelper class

This removes mBaseLevel from ImageHelper class. With the mFirstAllocatedLevel tracking exactly which GL level has been allocated, this cached mBaseLevel is no longer needed. Bug: b/181800403 Change-Id: I99d66c93b0c8f1bd20a5811b51f512a27927201e Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2795275 Commit-Queue: Charlie Lao <cclao@google.com> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarIan Elliott <ianelliott@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 41a34d6b
...@@ -1593,10 +1593,7 @@ angle::Result TextureVk::redefineLevel(const gl::Context *context, ...@@ -1593,10 +1593,7 @@ angle::Result TextureVk::redefineLevel(const gl::Context *context,
} }
bool isUpdateToSingleLevelImage = bool isUpdateToSingleLevelImage =
mImage->getLevelCount() == 1 && mImage->getBaseLevel() == levelIndexGL; mImage->getLevelCount() == 1 && mImage->getFirstAllocatedLevel() == levelIndexGL;
// If it is single level image, baseLevel must equal to firstAllocateLevel
ASSERT(!isUpdateToSingleLevelImage ||
mImage->getFirstAllocatedLevel() == mImage->getBaseLevel());
// If incompatible, and redefining the single-level image, release it so it can be // If incompatible, and redefining the single-level image, release it so it can be
// recreated immediately. This is an optimization to avoid an extra copy. // recreated immediately. This is an optimization to avoid an extra copy.
...@@ -1864,12 +1861,14 @@ angle::Result TextureVk::generateMipmap(const gl::Context *context) ...@@ -1864,12 +1861,14 @@ angle::Result TextureVk::generateMipmap(const gl::Context *context)
ASSERT(mImage->valid()); ASSERT(mImage->valid());
// If base level has changed, the front-end should have called syncState already. // If base level has changed, the front-end should have called syncState already.
ASSERT(mImage->getBaseLevel() == gl::LevelIndex(mState.getEffectiveBaseLevel())); ASSERT(mState.getImmutableFormat() ||
mImage->getFirstAllocatedLevel() == gl::LevelIndex(mState.getEffectiveBaseLevel()));
// Only staged update here is the robust resource init if any. // Only staged update here is the robust resource init if any.
ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::FullMipChain)); ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::FullMipChain));
vk::LevelIndex maxLevel = mImage->toVkLevel(gl::LevelIndex(mState.getMipmapMaxLevel())); vk::LevelIndex baseLevel = mImage->toVkLevel(gl::LevelIndex(mState.getEffectiveBaseLevel()));
vk::LevelIndex maxLevel = mImage->toVkLevel(gl::LevelIndex(mState.getMipmapMaxLevel()));
ASSERT(maxLevel != vk::LevelIndex(0)); ASSERT(maxLevel != vk::LevelIndex(0));
// If it's possible to generate mipmap in compute, that would give the best possible // If it's possible to generate mipmap in compute, that would give the best possible
...@@ -1888,7 +1887,7 @@ angle::Result TextureVk::generateMipmap(const gl::Context *context) ...@@ -1888,7 +1887,7 @@ angle::Result TextureVk::generateMipmap(const gl::Context *context)
kBlitFeatureFlags)) kBlitFeatureFlags))
{ {
// Otherwise, use blit if possible. // Otherwise, use blit if possible.
return mImage->generateMipmapsWithBlit(contextVk, maxLevel); return mImage->generateMipmapsWithBlit(contextVk, baseLevel, maxLevel);
} }
ANGLE_PERF_WARNING(contextVk->getDebug(), GL_DEBUG_SEVERITY_HIGH, ANGLE_PERF_WARNING(contextVk->getDebug(), GL_DEBUG_SEVERITY_HIGH,
...@@ -1904,33 +1903,29 @@ angle::Result TextureVk::setBaseLevel(const gl::Context *context, GLuint baseLev ...@@ -1904,33 +1903,29 @@ angle::Result TextureVk::setBaseLevel(const gl::Context *context, GLuint baseLev
} }
angle::Result TextureVk::updateBaseMaxLevels(ContextVk *contextVk, angle::Result TextureVk::updateBaseMaxLevels(ContextVk *contextVk,
gl::LevelIndex baseLevel, bool baseLevelChanged,
gl::LevelIndex maxLevel) bool maxLevelChanged)
{ {
if (!mImage) if (!mImage)
{ {
return angle::Result::Continue; return angle::Result::Continue;
} }
// Track the previous levels for use in update loop below // Caller already checked this. Shouldn't reach here if none of them are changed.
gl::LevelIndex previousBaseLevel = mImage->getBaseLevel(); ASSERT(baseLevelChanged || maxLevelChanged);
gl::LevelIndex previousMaxLevel = mImage->getMaxLevel();
gl::LevelIndex baseLevel(mState.getEffectiveBaseLevel());
gl::LevelIndex maxLevel(mState.getEffectiveMaxLevel());
ASSERT(baseLevel <= maxLevel); ASSERT(baseLevel <= maxLevel);
bool baseLevelChanged = baseLevel != previousBaseLevel;
bool maxLevelChanged = previousMaxLevel != maxLevel;
if (!(baseLevelChanged || maxLevelChanged))
{
// This scenario is a noop, most likely maxLevel has been lowered to a level that already
// reflects the current state of the image
return angle::Result::Continue;
}
if (!mImage->valid()) if (!mImage->valid())
{ {
// Track the levels in our ImageHelper // Track the levels in our ImageHelper
mImage->setBaseAndMaxLevels(baseLevel, maxLevel); if (!mState.getImmutableFormat())
{
mImage->setFirstAllocatedLevel(baseLevel);
}
mImage->setMaxLevel(maxLevel);
// No further work to do, let staged updates handle the new levels // No further work to do, let staged updates handle the new levels
return angle::Result::Continue; return angle::Result::Continue;
...@@ -1959,8 +1954,9 @@ angle::Result TextureVk::updateBaseMaxLevels(ContextVk *contextVk, ...@@ -1959,8 +1954,9 @@ angle::Result TextureVk::updateBaseMaxLevels(ContextVk *contextVk,
{ {
// Don't need to respecify the texture; but do need to update which vkImageView's are // Don't need to respecify the texture; but do need to update which vkImageView's are
// served up by ImageViewHelper // served up by ImageViewHelper
// Track the levels in our ImageHelper // Track the levels in our ImageHelper
mImage->setBaseAndMaxLevels(baseLevel, maxLevel); mImage->setMaxLevel(maxLevel);
// Update the current max level in ImageViewHelper // Update the current max level in ImageViewHelper
const gl::ImageDesc &baseLevelDesc = mState.getBaseLevelDesc(); const gl::ImageDesc &baseLevelDesc = mState.getBaseLevelDesc();
...@@ -1972,7 +1968,8 @@ angle::Result TextureVk::updateBaseMaxLevels(ContextVk *contextVk, ...@@ -1972,7 +1968,8 @@ angle::Result TextureVk::updateBaseMaxLevels(ContextVk *contextVk,
maxLevel - baseLevel + 1, layerCount); maxLevel - baseLevel + 1, layerCount);
} }
return respecifyImageStorageAndLevels(contextVk, previousBaseLevel, baseLevel, maxLevel); return respecifyImageStorageAndLevels(contextVk, mImage->getFirstAllocatedLevel(), baseLevel,
maxLevel);
} }
angle::Result TextureVk::copyAndStageImageData(ContextVk *contextVk, angle::Result TextureVk::copyAndStageImageData(ContextVk *contextVk,
...@@ -2027,8 +2024,8 @@ angle::Result TextureVk::respecifyImageStorageAndLevels(ContextVk *contextVk, ...@@ -2027,8 +2024,8 @@ angle::Result TextureVk::respecifyImageStorageAndLevels(ContextVk *contextVk,
{ {
if (!mImage->valid()) if (!mImage->valid())
{ {
ASSERT((mImage->getBaseLevel() == gl::LevelIndex(0)) || ASSERT((mImage->getFirstAllocatedLevel() == gl::LevelIndex(0)) ||
(mImage->getBaseLevel() == baseLevel)); (mImage->getFirstAllocatedLevel() == baseLevel));
ASSERT((mImage->getMaxLevel() == gl::LevelIndex(0)) || (mImage->getMaxLevel() == maxLevel)); ASSERT((mImage->getMaxLevel() == gl::LevelIndex(0)) || (mImage->getMaxLevel() == maxLevel));
releaseImage(contextVk); releaseImage(contextVk);
return angle::Result::Continue; return angle::Result::Continue;
...@@ -2079,7 +2076,7 @@ angle::Result TextureVk::respecifyImageStorageAndLevels(ContextVk *contextVk, ...@@ -2079,7 +2076,7 @@ angle::Result TextureVk::respecifyImageStorageAndLevels(ContextVk *contextVk,
// After flushing prior staged updates, track the new levels (they are used in the flush, hence // After flushing prior staged updates, track the new levels (they are used in the flush, hence
// the wait) // the wait)
dstImage->setBaseAndMaxLevels(baseLevel, maxLevel); dstImage->setMaxLevel(maxLevel);
// Transfer the entire contents of the source image into the destination image. // Transfer the entire contents of the source image into the destination image.
ANGLE_TRY(copyAndStageImageData(contextVk, previousFirstAllocateLevel, srcImage, dstImage)); ANGLE_TRY(copyAndStageImageData(contextVk, previousFirstAllocateLevel, srcImage, dstImage));
...@@ -2090,6 +2087,11 @@ angle::Result TextureVk::respecifyImageStorageAndLevels(ContextVk *contextVk, ...@@ -2090,6 +2087,11 @@ angle::Result TextureVk::respecifyImageStorageAndLevels(ContextVk *contextVk,
if (ownsCurrentImage) if (ownsCurrentImage)
{ {
releaseImage(contextVk); releaseImage(contextVk);
if (!mState.getImmutableFormat())
{
dstImage->setFirstAllocatedLevel(baseLevel);
}
} }
mImage->retain(&contextVk->getResourceUseList()); mImage->retain(&contextVk->getResourceUseList());
...@@ -2334,14 +2336,14 @@ void TextureVk::prepareForGenerateMipmap(ContextVk *contextVk) ...@@ -2334,14 +2336,14 @@ void TextureVk::prepareForGenerateMipmap(ContextVk *contextVk)
"levels mask assumes 32-bits is enough"); "levels mask assumes 32-bits is enough");
gl::TexLevelMask::value_type levelsMask = angle::Bit<uint32_t>(maxLevel + 1 - baseLevel) - 1; gl::TexLevelMask::value_type levelsMask = angle::Bit<uint32_t>(maxLevel + 1 - baseLevel) - 1;
gl::LevelIndex imageBaseLevel = mImage->getBaseLevel(); gl::LevelIndex imageAllocatedLevel = mImage->getFirstAllocatedLevel();
if (imageBaseLevel > baseLevel) if (imageAllocatedLevel > baseLevel)
{ {
levelsMask >>= imageBaseLevel - baseLevel; levelsMask >>= imageAllocatedLevel - baseLevel;
} }
else else
{ {
levelsMask <<= baseLevel - imageBaseLevel; levelsMask <<= baseLevel - imageAllocatedLevel;
} }
mRedefinedLevels &= gl::TexLevelMask(~levelsMask); mRedefinedLevels &= gl::TexLevelMask(~levelsMask);
...@@ -2434,11 +2436,11 @@ angle::Result TextureVk::syncState(const gl::Context *context, ...@@ -2434,11 +2436,11 @@ angle::Result TextureVk::syncState(const gl::Context *context,
} }
// Set base and max level before initializing the image // Set base and max level before initializing the image
if (dirtyBits.test(gl::Texture::DIRTY_BIT_MAX_LEVEL) || bool baseLevelChanged = dirtyBits.test(gl::Texture::DIRTY_BIT_BASE_LEVEL);
dirtyBits.test(gl::Texture::DIRTY_BIT_BASE_LEVEL)) bool maxLevelChanged = dirtyBits.test(gl::Texture::DIRTY_BIT_MAX_LEVEL);
if (maxLevelChanged || baseLevelChanged)
{ {
ANGLE_TRY(updateBaseMaxLevels(contextVk, gl::LevelIndex(mState.getEffectiveBaseLevel()), ANGLE_TRY(updateBaseMaxLevels(contextVk, baseLevelChanged, maxLevelChanged));
gl::LevelIndex(mState.getEffectiveMaxLevel())));
// Updating levels could have respecified the storage, recapture mImageCreateFlags // Updating levels could have respecified the storage, recapture mImageCreateFlags
oldCreateFlags = mImageCreateFlags; oldCreateFlags = mImageCreateFlags;
...@@ -2788,7 +2790,8 @@ angle::Result TextureVk::initImageViews(ContextVk *contextVk, ...@@ -2788,7 +2790,8 @@ angle::Result TextureVk::initImageViews(ContextVk *contextVk,
{ {
ASSERT(mImage != nullptr && mImage->valid()); ASSERT(mImage != nullptr && mImage->valid());
gl::LevelIndex baseLevelGL = getNativeImageLevel(mImage->getBaseLevel()); gl::LevelIndex baseLevelGL =
getNativeImageLevel(gl::LevelIndex(mState.getEffectiveBaseLevel()));
vk::LevelIndex baseLevelVk = mImage->toVkLevel(baseLevelGL); vk::LevelIndex baseLevelVk = mImage->toVkLevel(baseLevelGL);
uint32_t baseLayer = getNativeImageLayer(0); uint32_t baseLayer = getNativeImageLayer(0);
......
...@@ -450,8 +450,8 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface ...@@ -450,8 +450,8 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface
// Update base and max levels, and re-create image if needed. // Update base and max levels, and re-create image if needed.
angle::Result updateBaseMaxLevels(ContextVk *contextVk, angle::Result updateBaseMaxLevels(ContextVk *contextVk,
gl::LevelIndex baseLevelGL, bool baseLevelChanged,
gl::LevelIndex maxLevelGL); bool maxLevelChanged);
bool isFastUnpackPossible(const vk::Format &vkFormat, size_t offset) const; bool isFastUnpackPossible(const vk::Format &vkFormat, size_t offset) const;
......
...@@ -3272,7 +3272,7 @@ angle::Result UtilsVk::cullOverlayWidgets(ContextVk *contextVk, ...@@ -3272,7 +3272,7 @@ angle::Result UtilsVk::cullOverlayWidgets(ContextVk *contextVk,
&descriptorSet)); &descriptorSet));
ASSERT(dest->getLevelCount() == 1 && dest->getLayerCount() == 1 && ASSERT(dest->getLevelCount() == 1 && dest->getLayerCount() == 1 &&
dest->getBaseLevel() == gl::LevelIndex(0)); dest->getFirstAllocatedLevel() == gl::LevelIndex(0));
vk::CommandBufferAccess access; vk::CommandBufferAccess access;
access.onBufferComputeShaderRead(enabledWidgetsBuffer); access.onBufferComputeShaderRead(enabledWidgetsBuffer);
...@@ -3349,7 +3349,7 @@ angle::Result UtilsVk::drawOverlay(ContextVk *contextVk, ...@@ -3349,7 +3349,7 @@ angle::Result UtilsVk::drawOverlay(ContextVk *contextVk,
&descriptorSet)); &descriptorSet));
ASSERT(dest->getLevelCount() == 1 && dest->getLayerCount() == 1 && ASSERT(dest->getLevelCount() == 1 && dest->getLayerCount() == 1 &&
dest->getBaseLevel() == gl::LevelIndex(0)); dest->getFirstAllocatedLevel() == gl::LevelIndex(0));
vk::CommandBufferAccess access; vk::CommandBufferAccess access;
access.onImageComputeShaderWrite(gl::LevelIndex(0), 1, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, dest); access.onImageComputeShaderWrite(gl::LevelIndex(0), 1, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, dest);
......
...@@ -3636,7 +3636,6 @@ ImageHelper::ImageHelper(ImageHelper &&other) ...@@ -3636,7 +3636,6 @@ ImageHelper::ImageHelper(ImageHelper &&other)
mYuvConversionSampler(std::move(other.mYuvConversionSampler)), mYuvConversionSampler(std::move(other.mYuvConversionSampler)),
mExternalFormat(other.mExternalFormat), mExternalFormat(other.mExternalFormat),
mFirstAllocatedLevel(other.mFirstAllocatedLevel), mFirstAllocatedLevel(other.mFirstAllocatedLevel),
mBaseLevel(other.mBaseLevel),
mMaxLevel(other.mMaxLevel), mMaxLevel(other.mMaxLevel),
mLayerCount(other.mLayerCount), mLayerCount(other.mLayerCount),
mLevelCount(other.mLevelCount), mLevelCount(other.mLevelCount),
...@@ -3671,7 +3670,6 @@ void ImageHelper::resetCachedProperties() ...@@ -3671,7 +3670,6 @@ void ImageHelper::resetCachedProperties()
mLastNonShaderReadOnlyLayout = ImageLayout::Undefined; mLastNonShaderReadOnlyLayout = ImageLayout::Undefined;
mCurrentShaderReadStageMask = 0; mCurrentShaderReadStageMask = 0;
mFirstAllocatedLevel = gl::LevelIndex(0); mFirstAllocatedLevel = gl::LevelIndex(0);
mBaseLevel = gl::LevelIndex(0);
mMaxLevel = gl::LevelIndex(0); mMaxLevel = gl::LevelIndex(0);
mLayerCount = 0; mLayerCount = 0;
mLevelCount = 0; mLevelCount = 0;
...@@ -3840,7 +3838,6 @@ angle::Result ImageHelper::initExternal(Context *context, ...@@ -3840,7 +3838,6 @@ angle::Result ImageHelper::initExternal(Context *context,
mSamples = std::max(samples, 1); mSamples = std::max(samples, 1);
mImageSerial = context->getRenderer()->getResourceSerialFactory().generateImageSerial(); mImageSerial = context->getRenderer()->getResourceSerialFactory().generateImageSerial();
mFirstAllocatedLevel = immutable ? gl::LevelIndex(0) : baseLevel; mFirstAllocatedLevel = immutable ? gl::LevelIndex(0) : baseLevel;
mBaseLevel = baseLevel;
mMaxLevel = maxLevel; mMaxLevel = maxLevel;
mLevelCount = mipLevels; mLevelCount = mipLevels;
mLayerCount = layerCount; mLayerCount = layerCount;
...@@ -4565,17 +4562,18 @@ bool ImageHelper::isReleasedToExternal() const ...@@ -4565,17 +4562,18 @@ bool ImageHelper::isReleasedToExternal() const
#endif #endif
} }
void ImageHelper::setBaseAndMaxLevels(gl::LevelIndex baseLevel, gl::LevelIndex maxLevel) void ImageHelper::setFirstAllocatedLevel(gl::LevelIndex firstLevel)
{ {
mBaseLevel = baseLevel;
mMaxLevel = maxLevel;
// For immutable texture, we always allocate the entire mipmap chain [0, mLevelCount-1]. // For immutable texture, we always allocate the entire mipmap chain [0, mLevelCount-1].
// For mutable textures, we will try to reallocate based on baseLevel change // For mutable textures, we will try to reallocate based on baseLevel change
if (!mImmutable) ASSERT(!mImmutable);
{ ASSERT(!valid());
mFirstAllocatedLevel = baseLevel; mFirstAllocatedLevel = firstLevel;
} }
void ImageHelper::setMaxLevel(gl::LevelIndex maxLevel)
{
mMaxLevel = maxLevel;
} }
LevelIndex ImageHelper::toVkLevel(gl::LevelIndex levelIndexGL) const LevelIndex ImageHelper::toVkLevel(gl::LevelIndex levelIndexGL) const
...@@ -4943,10 +4941,13 @@ angle::Result ImageHelper::CopyImageSubData(const gl::Context *context, ...@@ -4943,10 +4941,13 @@ angle::Result ImageHelper::CopyImageSubData(const gl::Context *context,
return angle::Result::Continue; return angle::Result::Continue;
} }
angle::Result ImageHelper::generateMipmapsWithBlit(ContextVk *contextVk, LevelIndex maxLevel) angle::Result ImageHelper::generateMipmapsWithBlit(ContextVk *contextVk,
LevelIndex baseLevel,
LevelIndex maxLevel)
{ {
CommandBufferAccess access; CommandBufferAccess access;
access.onImageTransferWrite(mBaseLevel + 1, maxLevel.get(), 0, mLayerCount, gl::LevelIndex baseLevelGL = toGLLevel(baseLevel);
access.onImageTransferWrite(baseLevelGL + 1, maxLevel.get(), 0, mLayerCount,
VK_IMAGE_ASPECT_COLOR_BIT, this); VK_IMAGE_ASPECT_COLOR_BIT, this);
CommandBuffer *commandBuffer; CommandBuffer *commandBuffer;
...@@ -4970,7 +4971,6 @@ angle::Result ImageHelper::generateMipmapsWithBlit(ContextVk *contextVk, LevelIn ...@@ -4970,7 +4971,6 @@ angle::Result ImageHelper::generateMipmapsWithBlit(ContextVk *contextVk, LevelIn
barrier.subresourceRange.levelCount = 1; barrier.subresourceRange.levelCount = 1;
const VkFilter filter = gl_vk::GetFilter(CalculateGenerateMipmapFilter(contextVk, getFormat())); const VkFilter filter = gl_vk::GetFilter(CalculateGenerateMipmapFilter(contextVk, getFormat()));
LevelIndex baseLevelVk = toVkLevel(mBaseLevel);
for (LevelIndex mipLevel(1); mipLevel <= LevelIndex(mLevelCount); ++mipLevel) for (LevelIndex mipLevel(1); mipLevel <= LevelIndex(mLevelCount); ++mipLevel)
{ {
...@@ -4978,7 +4978,7 @@ angle::Result ImageHelper::generateMipmapsWithBlit(ContextVk *contextVk, LevelIn ...@@ -4978,7 +4978,7 @@ angle::Result ImageHelper::generateMipmapsWithBlit(ContextVk *contextVk, LevelIn
int32_t nextMipHeight = std::max<int32_t>(1, mipHeight >> 1); int32_t nextMipHeight = std::max<int32_t>(1, mipHeight >> 1);
int32_t nextMipDepth = std::max<int32_t>(1, mipDepth >> 1); int32_t nextMipDepth = std::max<int32_t>(1, mipDepth >> 1);
if (mipLevel > baseLevelVk && mipLevel <= maxLevel) if (mipLevel > baseLevel && mipLevel <= maxLevel)
{ {
barrier.subresourceRange.baseMipLevel = mipLevel.get() - 1; barrier.subresourceRange.baseMipLevel = mipLevel.get() - 1;
barrier.oldLayout = getCurrentLayout(); barrier.oldLayout = getCurrentLayout();
......
...@@ -1613,7 +1613,9 @@ class ImageHelper final : public Resource, public angle::Subject ...@@ -1613,7 +1613,9 @@ class ImageHelper final : public Resource, public angle::Subject
GLsizei srcDepth); GLsizei srcDepth);
// Generate mipmap from level 0 into the rest of the levels with blit. // Generate mipmap from level 0 into the rest of the levels with blit.
angle::Result generateMipmapsWithBlit(ContextVk *contextVk, LevelIndex maxLevel); angle::Result generateMipmapsWithBlit(ContextVk *contextVk,
LevelIndex baseLevel,
LevelIndex maxLevel);
// Resolve this image into a destination image. This image should be in the TransferSrc layout. // Resolve this image into a destination image. This image should be in the TransferSrc layout.
// The destination image is automatically transitioned into TransferDst. // The destination image is automatically transitioned into TransferDst.
...@@ -1792,8 +1794,8 @@ class ImageHelper final : public Resource, public angle::Subject ...@@ -1792,8 +1794,8 @@ class ImageHelper final : public Resource, public angle::Subject
bool isReleasedToExternal() const; bool isReleasedToExternal() const;
gl::LevelIndex getFirstAllocatedLevel() const { return mFirstAllocatedLevel; } gl::LevelIndex getFirstAllocatedLevel() const { return mFirstAllocatedLevel; }
gl::LevelIndex getBaseLevel() const { return mBaseLevel; } void setFirstAllocatedLevel(gl::LevelIndex firstLevel);
void setBaseAndMaxLevels(gl::LevelIndex baseLevel, gl::LevelIndex maxLevel); void setMaxLevel(gl::LevelIndex maxLevel);
gl::LevelIndex getMaxLevel() const { return mMaxLevel; } gl::LevelIndex getMaxLevel() const { return mMaxLevel; }
LevelIndex toVkLevel(gl::LevelIndex levelIndexGL) const; LevelIndex toVkLevel(gl::LevelIndex levelIndexGL) const;
gl::LevelIndex toGLLevel(LevelIndex levelIndexVk) const; gl::LevelIndex toGLLevel(LevelIndex levelIndexVk) const;
...@@ -2068,7 +2070,6 @@ class ImageHelper final : public Resource, public angle::Subject ...@@ -2068,7 +2070,6 @@ class ImageHelper final : public Resource, public angle::Subject
gl::LevelIndex mFirstAllocatedLevel; gl::LevelIndex mFirstAllocatedLevel;
// Cached properties. // Cached properties.
gl::LevelIndex mBaseLevel;
gl::LevelIndex mMaxLevel; gl::LevelIndex mMaxLevel;
uint32_t mLayerCount; uint32_t mLayerCount;
uint32_t mLevelCount; uint32_t mLevelCount;
......
...@@ -3922,6 +3922,61 @@ TEST_P(Texture2DBaseMaxTestES3, StageInvalidLevels) ...@@ -3922,6 +3922,61 @@ TEST_P(Texture2DBaseMaxTestES3, StageInvalidLevels)
} }
} }
// Test redefine a mutable texture into an immutable texture.
TEST_P(Texture2DBaseMaxTestES3, RedefineMutableToImmutable)
{
// http://anglebug.com/4710
ANGLE_SKIP_TEST_IF(IsD3D());
// http://anglebug.com/4701
ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsOSX());
constexpr uint32_t kBaseLevel = 1;
const GLColor kNewMipColors[kMipCount] = {
GLColor::yellow,
GLColor::cyan,
GLColor::white,
GLColor(127u, 127u, 127u, 255u),
};
initTest(false);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, kBaseLevel);
// Test that all mips have the expected data
for (uint32_t lod = kBaseLevel; lod < kMipCount; ++lod)
{
setLodUniform(lod - kBaseLevel);
drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
}
glTexStorage2D(GL_TEXTURE_2D, kMipCount, GL_RGBA8, kMip0Size, kMip0Size);
std::array<GLColor, getTotalMipDataSize(kMip0Size)> mipData;
fillMipData(mipData.data(), kMip0Size, kNewMipColors);
for (size_t mip = 0; mip < kMipCount; ++mip)
{
glTexSubImage2D(GL_TEXTURE_2D, mip, 0, 0, kMip0Size >> mip, kMip0Size >> mip, GL_RGBA,
GL_UNSIGNED_BYTE, mipData.data() + getMipDataOffset(kMip0Size, mip));
}
// Test that all enabled mips have the expected data
for (uint32_t lod = kBaseLevel; lod < kMipCount; ++lod)
{
setLodUniform(lod - kBaseLevel);
drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[lod]);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
for (uint32_t lod = 0; lod < kBaseLevel; ++lod)
{
setLodUniform(lod);
drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[lod]);
}
}
// Test to check that texture completeness is determined correctly when the texture base level is // 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. // greater than 0, and also that level 0 is not sampled when base level is greater than 0.
TEST_P(Texture2DTestES3, DrawWithBaseLevel1) 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