Commit b5a71140 by Charlie Lao Committed by Commit Bot

Vulkan: Make storage actually immutable for immutable textures

The immutable textures are intended to be "immutable". Right now we are still re-allocating VkImage object based on base_level and max_level. This causes a problem for rendering to a level that is beyond [base_level, max_level], which is totally within OpenGL spec. This CL makes an immutable texture always allocate from 0 to max levels that are specified by a glTexStorage call. Changing base_level will not trigger re-allocation of VkImage object. Bug: b/181800403 Change-Id: I4b4ddea17b7f6f7bfd8f36bfe8bb3a35b5c180b6 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2368038Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarIan Elliott <ianelliott@google.com> Commit-Queue: Charlie Lao <cclao@google.com>
parent 969b8f31
......@@ -263,6 +263,12 @@ const ImageDesc &TextureState::getBaseLevelDesc() const
return getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
}
const ImageDesc &TextureState::getLevelZeroDesc() const
{
ASSERT(mType != TextureType::CubeMap || isCubeComplete());
return getImageDesc(getBaseImageTarget(), 0);
}
void TextureState::setCrop(const Rectangle &rect)
{
mCropRect = rect;
......@@ -1517,13 +1523,12 @@ angle::Result Texture::setStorage(Context *context,
mState.mImmutableFormat = true;
mState.mImmutableLevels = static_cast<GLuint>(levels);
ANGLE_TRY(mTexture->setStorage(context, type, levels, internalFormat, size));
mState.clearImageDescs();
mState.setImageDescChain(0, static_cast<GLuint>(levels - 1), size, Format(internalFormat),
InitState::MayNeedInit);
ANGLE_TRY(mTexture->setStorage(context, type, levels, internalFormat, size));
// Changing the texture to immutable can trigger a change in the base and max levels:
// GLES 3.0.4 section 3.8.10 pg 158:
// "For immutable-format textures, levelbase is clamped to the range[0;levels],levelmax is then
......@@ -1581,15 +1586,15 @@ angle::Result Texture::setStorageMultisample(Context *context,
const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
samples = formatCaps.getNearestSamples(samples);
ANGLE_TRY(mTexture->setStorageMultisample(context, type, samples, internalFormat, size,
fixedSampleLocations));
mState.mImmutableFormat = true;
mState.mImmutableLevels = static_cast<GLuint>(1);
mState.clearImageDescs();
mState.setImageDescChainMultisample(size, Format(internalFormat), samples, fixedSampleLocations,
InitState::MayNeedInit);
ANGLE_TRY(mTexture->setStorageMultisample(context, type, samples, internalFormat, size,
fixedSampleLocations));
signalDirtyStorage(InitState::MayNeedInit);
return angle::Result::Continue;
......
......@@ -152,6 +152,7 @@ class TextureState final : private angle::NonCopyable
// Returns the desc of the base level. Only valid for cube-complete/mip-complete textures.
const ImageDesc &getBaseLevelDesc() const;
const ImageDesc &getLevelZeroDesc() const;
// GLES1 emulation: For GL_OES_draw_texture
void setCrop(const Rectangle &rect);
......
......@@ -208,7 +208,7 @@ angle::Result MemoryObjectVk::createImage(ContextVk *contextVk,
contextVk, type, vkExtents, vkFormat, 1, imageUsageFlags, createFlags,
vk::ImageLayout::Undefined, &externalMemoryImageCreateInfo, gl::LevelIndex(0),
gl::LevelIndex(static_cast<uint32_t>(levels) - 1), static_cast<uint32_t>(levels),
layerCount, contextVk->isRobustResourceInitEnabled(), nullptr));
layerCount, contextVk->isRobustResourceInitEnabled(), false, nullptr));
VkMemoryRequirements externalMemoryRequirements;
image->getImage().getMemoryRequirements(renderer->getDevice(), &externalMemoryRequirements);
......
......@@ -106,7 +106,7 @@ angle::Result RenderbufferVk::setStorageImpl(const gl::Context *context,
ANGLE_TRY(mImage->initExternal(contextVk, gl::TextureType::_2D, extents, format, imageSamples,
usage, vk::kVkImageCreateFlagsNone, vk::ImageLayout::Undefined,
nullptr, gl::LevelIndex(0), gl::LevelIndex(0), 1, 1, robustInit,
nullptr));
false, nullptr));
VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
ANGLE_TRY(mImage->initMemory(contextVk, renderer->getMemoryProperties(), flags));
......
......@@ -134,7 +134,7 @@ angle::Result InitImageHelper(DisplayVk *displayVk,
ANGLE_TRY(imageHelper->initExternal(
displayVk, gl::TextureType::_2D, extents, vkFormat, samples, usage,
vk::kVkImageCreateFlagsNone, vk::ImageLayout::Undefined, nullptr, gl::LevelIndex(0),
gl::LevelIndex(0), 1, 1, isRobustResourceInitEnabled, nullptr));
gl::LevelIndex(0), 1, 1, isRobustResourceInitEnabled, false, nullptr));
return angle::Result::Continue;
}
......
......@@ -412,12 +412,13 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface
const bool sized,
const gl::Extents &extents,
const uint32_t levelCount);
angle::Result initImmutableImage(ContextVk *contextVk, const vk::Format &format);
void releaseImage(ContextVk *contextVk);
void releaseStagingBuffer(ContextVk *contextVk);
uint32_t getMipLevelCount(ImageMipLevels mipLevels) const;
uint32_t getMaxLevelCount() const;
angle::Result copyAndStageImageData(ContextVk *contextVk,
gl::LevelIndex previousBaseLevel,
gl::LevelIndex previousFirstAllocateLevel,
vk::ImageHelper *srcImage,
vk::ImageHelper *dstImage);
angle::Result initImageViews(ContextVk *contextVk,
......@@ -443,7 +444,7 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface
// attributes at the next opportunity.
angle::Result respecifyImageStorage(ContextVk *contextVk);
angle::Result respecifyImageStorageAndLevels(ContextVk *contextVk,
gl::LevelIndex previousBaseLevelGL,
gl::LevelIndex previousFirstAllocateLevelGL,
gl::LevelIndex baseLevelGL,
gl::LevelIndex maxLevelGL);
......
......@@ -264,7 +264,7 @@ angle::Result HardwareBufferImageSiblingVkAndroid::initImpl(DisplayVk *displayVk
bufferFormatProperties.format == VK_FORMAT_UNDEFINED ? externalVkFormat : vkFormat, 1,
usage, vk::kVkImageCreateFlagsNone, vk::ImageLayout::ExternalPreInitialized,
&externalMemoryImageCreateInfo, gl::LevelIndex(0), gl::LevelIndex(0), 1, 1,
robustInitEnabled, nullptr));
robustInitEnabled, false, nullptr));
VkImportAndroidHardwareBufferInfoANDROID importHardwareBufferInfo = {};
importHardwareBufferInfo.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID;
......
......@@ -1449,6 +1449,7 @@ class ImageHelper final : public Resource, public angle::Subject
uint32_t mipLevels,
uint32_t layerCount,
bool isRobustResourceInitEnabled,
bool immutable,
bool *imageFormatListEnabledOut);
angle::Result initMemory(Context *context,
const MemoryProperties &memoryProperties,
......@@ -1790,6 +1791,7 @@ class ImageHelper final : public Resource, public angle::Subject
// Returns true if the image is owned by an external API or instance.
bool isReleasedToExternal() const;
gl::LevelIndex getFirstAllocatedLevel() const { return mFirstAllocatedLevel; }
gl::LevelIndex getBaseLevel() const { return mBaseLevel; }
void setBaseAndMaxLevels(gl::LevelIndex baseLevel, gl::LevelIndex maxLevel);
gl::LevelIndex getMaxLevel() const { return mMaxLevel; }
......@@ -2040,6 +2042,9 @@ class ImageHelper final : public Resource, public angle::Subject
// different between the rotated and non-rotated extents.
VkExtent3D mExtents;
bool mRotatedAspectRatio;
// True if this is created by an immutable texture glTexStorage. For immutable texture, the
// underlying VkImage object is always created from level 0 to mLevelCount-1.
bool mImmutable;
const Format *mFormat;
GLint mSamples;
ImageSerial mImageSerial;
......@@ -2057,6 +2062,11 @@ class ImageHelper final : public Resource, public angle::Subject
BindingPointer<SamplerYcbcrConversion> mYuvConversionSampler;
uint64_t mExternalFormat;
// The first level that has been allocated. For mutable textures, this should be same as
// mBaseLevel since we always reallocate VkImage based on mBaseLevel change. But for immutable
// textures, we always allocate from level 0 regardless of mBaseLevel change.
gl::LevelIndex mFirstAllocatedLevel;
// Cached properties.
gl::LevelIndex mBaseLevel;
gl::LevelIndex mMaxLevel;
......
......@@ -129,3 +129,6 @@
// New failures with latest dEQP roll (2020-04-28)
4593 SWIFTSHADER : KHR-GLES31.core.nearest_edge.offset_left = FAIL
// Test timeout due to it loops so many glTexStorageMultisample calls
5806 VULKAN NVIDIA : KHR-GLES31.core.texture_storage_multisample.APIDependencies.fbo_with_renderbuffer_and_multisample_texture_attachments_with_different_number_of_samples = SKIP
......@@ -2546,7 +2546,7 @@ TEST_P(FramebufferTest_ES3, SampleFromAttachedTextureWithDifferentLOD)
TEST_P(FramebufferTest_ES3, RenderAndInvalidateImmutableTextureWithBeyondMaxLevel)
{
// ToDo: https://issuetracker.google.com/181800403
ANGLE_SKIP_TEST_IF(IsVulkan() || IsMetal());
ANGLE_SKIP_TEST_IF(IsMetal());
constexpr GLuint kLevel0Size = 4;
constexpr GLuint kLevel1Size = kLevel0Size / 2;
......@@ -2596,7 +2596,7 @@ TEST_P(FramebufferTest_ES3, RenderAndInvalidateImmutableTextureWithBeyondMaxLeve
TEST_P(FramebufferTest_ES3, RenderAndInvalidateImmutableTextureWithSubImageWithBeyondMaxLevel)
{
// ToDo: https://issuetracker.google.com/181800403
ANGLE_SKIP_TEST_IF(IsVulkan() || IsMetal());
ANGLE_SKIP_TEST_IF(IsMetal());
constexpr GLuint kLevel0Size = 4;
constexpr GLuint kLevel1Size = kLevel0Size / 2;
......@@ -2652,7 +2652,7 @@ TEST_P(FramebufferTest_ES3, RenderAndInvalidateImmutableTextureWithSubImageWithB
TEST_P(FramebufferTest_ES3, RenderAndInvalidateImmutableTextureWithBellowBaseLevelLOD)
{
// ToDo: https://issuetracker.google.com/181800403
ANGLE_SKIP_TEST_IF(IsVulkan() || IsMetal());
ANGLE_SKIP_TEST_IF(IsMetal());
constexpr GLuint kLevel0Size = 4;
constexpr GLuint kLevel1Size = kLevel0Size / 2;
......
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