Commit 3d2de99e by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Fix RTs attached to textures with non-0 mip

Cleared confusion between GL level indices and VK level indices by adding the corresponding suffix to variables and function arguments. A handful of places that sent one index and expected the other are fixed. The conversion between the two is given by: levelIndexGL = levelIndexVk + baseLevel; Bug: angleproject:4695 Change-Id: I84ecbaf867d00a40fb39b6db7ad79658016f4d9a Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2235362 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent d80d9044
......@@ -1700,10 +1700,10 @@ angle::Result FramebufferVk::readPixelsImpl(ContextVk *contextVk,
void *pixels)
{
ANGLE_TRACE_EVENT0("gpu.angle", "FramebufferVk::readPixelsImpl");
uint32_t level = renderTarget->getLevelIndex();
uint32_t layer = renderTarget->getLayerIndex();
uint32_t levelGL = renderTarget->getLevelIndex();
uint32_t layer = renderTarget->getLayerIndex();
return renderTarget->getImage().readPixels(contextVk, area, packPixelsParams, copyAspectFlags,
level, layer, pixels, &mReadPixelBuffer);
levelGL, layer, pixels, &mReadPixelBuffer);
}
gl::Extents FramebufferVk::getReadImageExtents() const
......
......@@ -1199,8 +1199,8 @@ angle::Result TextureVk::copyAndStageImageSubresource(ContextVk *contextVk,
const gl::ImageDesc &desc,
bool ignoreLayerCount,
uint32_t currentLayer,
uint32_t sourceMipLevel,
uint32_t stagingDstMipLevel)
uint32_t srcLevelVk,
uint32_t dstLevelGL)
{
const gl::Extents &baseLevelExtents = desc.size;
......@@ -1221,9 +1221,9 @@ angle::Result TextureVk::copyAndStageImageSubresource(ContextVk *contextVk,
vk::BufferHelper *stagingBuffer = nullptr;
vk::StagingBufferOffsetArray stagingBufferOffsets = {0, 0};
size_t bufferSize = 0;
ANGLE_TRY(mImage->copyImageDataToBuffer(contextVk, sourceMipLevel, layerCount, currentLayer,
area, &stagingBuffer, &bufferSize,
&stagingBufferOffsets, nullptr));
ANGLE_TRY(mImage->copyImageDataToBuffer(contextVk, srcLevelVk, layerCount, currentLayer, area,
&stagingBuffer, &bufferSize, &stagingBufferOffsets,
nullptr));
// Stage an update to the new image
ASSERT(stagingBuffer);
......@@ -1238,7 +1238,7 @@ angle::Result TextureVk::copyAndStageImageSubresource(ContextVk *contextVk,
bufferImageHeight = std::max(bufferImageHeight, desc.format.info->compressedBlockHeight);
}
ANGLE_TRY(mImage->stageSubresourceUpdateFromBuffer(
contextVk, bufferSize, stagingDstMipLevel, currentLayer, layerCount, bufferRowLength,
contextVk, bufferSize, dstLevelGL, currentLayer, layerCount, bufferRowLength,
bufferImageHeight, updatedExtents, offset, stagingBuffer, stagingBufferOffsets));
return angle::Result::Continue;
......@@ -1305,47 +1305,31 @@ angle::Result TextureVk::respecifyImageAttributesAndLevels(ContextVk *contextVk,
mImage->getLayerCount(), commandBuffer));
}
bool baseLevelChanged = baseLevel != previousBaseLevel;
// After flushing, track the new levels (they are used in the flush, hence the wait)
mImage->setBaseAndMaxLevels(baseLevel, maxLevel);
// Next, back up any data we need to preserve by staging it as updates to the new image.
// Stage updates for all levels in the GL texture, while preserving the data in the vkImage.
// This ensures we propagate all the current image data, even as max level moves around.
uint32_t updateCount =
std::max<GLuint>(mState.getMipmapMaxLevel() + 1, mImage->getLevelCount());
// Preserve the data in the Vulkan image. GL texture's staged updates that correspond to levels
// outside the range of the Vulkan image will remain intact.
// The staged updates won't be applied until the image has the requisite mip levels
for (uint32_t layer = 0; layer < mImage->getLayerCount(); layer++)
{
for (uint32_t level = 0; level < updateCount; level++)
for (uint32_t levelVK = 0; levelVK < mImage->getLevelCount(); levelVK++)
{
if (mImage->isUpdateStaged(level, layer))
{
// If there is still an update staged for the surface at the designated
// layer/level, we don't need to propagate any data from this image.
// This can happen for original texture levels that have never fit into
// the vkImage due to base/max level, and for vkImage data that has been
// staged by previous calls to respecifyImageAttributesAndLevels that didn't fit
// into the new vkImage.
continue;
}
// Vulkan level 0 previously aligned with whatever the base level was.
uint32_t levelGL = levelVK + previousBaseLevel;
ASSERT(!mImage->isUpdateStaged(levelGL, layer));
// Pull data from the current image and stage it as an update for the new image
// First we populate the staging buffer with current level data
const gl::ImageDesc &desc =
mState.getImageDesc(gl::TextureTypeToTarget(mState.getType(), layer), level);
// We need to adjust the source Vulkan level to reflect the previous base level.
// vk level 0 previously aligned with whatever the base level was.
uint32_t srcLevelVK = baseLevelChanged ? level - previousBaseLevel : level;
ASSERT(srcLevelVK <= mImage->getLevelCount());
mState.getImageDesc(gl::TextureTypeToTarget(mState.getType(), layer), levelGL);
ANGLE_TRY(
copyAndStageImageSubresource(contextVk, desc, true, layer, srcLevelVK, level));
ANGLE_TRY(copyAndStageImageSubresource(contextVk, desc, true, layer, levelVK, levelGL));
}
}
......
......@@ -356,8 +356,8 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface
const gl::ImageDesc &desc,
bool ignoreLayerCount,
uint32_t currentLayer,
uint32_t sourceLevel,
uint32_t stagingDstMipLevel);
uint32_t srcLevelVk,
uint32_t dstLevelGL);
angle::Result initImageViews(ContextVk *contextVk,
const vk::Format &format,
const bool sized,
......
......@@ -1164,7 +1164,7 @@ class ImageHelper final : public Resource, public angle::Subject
void resolve(ImageHelper *dest, const VkImageResolve &region, CommandBuffer *commandBuffer);
// Data staging
void removeStagedUpdates(ContextVk *contextVk, uint32_t levelIndex, uint32_t layerIndex);
void removeStagedUpdates(ContextVk *contextVk, uint32_t levelIndexGL, uint32_t layerIndex);
angle::Result stageSubresourceUpdateImpl(ContextVk *contextVk,
const gl::ImageIndex &index,
......@@ -1198,7 +1198,7 @@ class ImageHelper final : public Resource, public angle::Subject
angle::Result stageSubresourceUpdateFromBuffer(ContextVk *contextVk,
size_t allocationSize,
uint32_t mipLevel,
uint32_t mipLevelGL,
uint32_t baseArrayLayer,
uint32_t layerCount,
uint32_t bufferRowLength,
......@@ -1246,7 +1246,7 @@ class ImageHelper final : public Resource, public angle::Subject
// Flush staged updates for a single subresource. Can optionally take a parameter to defer
// clears to a subsequent RenderPass load op.
angle::Result flushSingleSubresourceStagedUpdates(ContextVk *contextVk,
uint32_t level,
uint32_t levelGL,
uint32_t layer,
CommandBuffer *commandBuffer,
ClearValuesArray *deferredClears,
......@@ -1267,7 +1267,7 @@ class ImageHelper final : public Resource, public angle::Subject
// as with renderbuffers or surface images.
angle::Result flushAllStagedUpdates(ContextVk *contextVk);
bool isUpdateStaged(uint32_t level, uint32_t layer);
bool isUpdateStaged(uint32_t levelGL, uint32_t layer);
bool hasStagedUpdates() const { return !mSubresourceUpdates.empty(); }
// changeLayout automatically skips the layout change if it's unnecessary. This function can be
......@@ -1346,7 +1346,7 @@ class ImageHelper final : public Resource, public angle::Subject
angle::Result readPixelsForGetImage(ContextVk *contextVk,
const gl::PixelPackState &packState,
gl::Buffer *packBuffer,
uint32_t level,
uint32_t levelGL,
uint32_t layer,
GLenum format,
GLenum type,
......@@ -1356,7 +1356,7 @@ class ImageHelper final : public Resource, public angle::Subject
const gl::Rectangle &area,
const PackPixelsParams &packPixelsParams,
VkImageAspectFlagBits copyAspectFlags,
uint32_t level,
uint32_t levelGL,
uint32_t layer,
void *pixels,
DynamicBuffer *stagingBuffer);
......@@ -1411,11 +1411,12 @@ class ImageHelper final : public Resource, public angle::Subject
const VkImageSubresourceLayers &dstSubresource() const
{
// Note: destination mip level includes base level.
ASSERT(updateSource == UpdateSource::Buffer || updateSource == UpdateSource::Image);
return updateSource == UpdateSource::Buffer ? buffer.copyRegion.imageSubresource
: image.copyRegion.dstSubresource;
}
bool isUpdateToLayerLevel(uint32_t layerIndex, uint32_t levelIndex) const;
bool isUpdateToLayerLevel(uint32_t layerIndex, uint32_t levelIndexGL) const;
UpdateSource updateSource;
union
......
......@@ -464,9 +464,6 @@ TEST_P(FramebufferTest_ES3, TextureAttachmentMipLevels)
TEST_P(FramebufferTest_ES3, TextureAttachmentMipLevelsReadBack)
{
// http://anglebug.com/4695
ANGLE_SKIP_TEST_IF(IsVulkan());
GLFramebuffer framebuffer;
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
......
......@@ -2412,11 +2412,6 @@ TEST_P(Texture2DTestES3, FramebufferTextureChangingBaselevel)
// preserves the other mips' data.
TEST_P(Texture2DBaseMaxTestES3, ExtendMipChainAfterRedefine)
{
// Affected by two bugs:
// - http://anglebug.com/4695
// - http://anglebug.com/4696
ANGLE_SKIP_TEST_IF(IsVulkan());
// http://anglebug.com/4699
ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsOSX());
......@@ -2442,6 +2437,9 @@ TEST_P(Texture2DBaseMaxTestES3, ExtendMipChainAfterRedefine)
// Mip 1 is green. Verify this.
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
// http://anglebug.com/4696
ANGLE_SKIP_TEST_IF(IsVulkan());
// Add mip 0 and rebase the mip chain.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
mipData.data() + getMipDataOffset(kMip0Size, 0));
......
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