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