Commit 34eb401b by Charlie Lao Committed by Commit Bot

Vulkan: Skip repeated VkCmdClear call with the same value

Some apps actually do this. One of them is gfxbench. This helps performance by dropping the redundant clear calls. Bug: b/159489614 Change-Id: Ib7958042f081b8fd58c5bc912fbb45bb223aec0f Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2255643Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Charlie Lao <cclao@google.com>
parent a52834d8
......@@ -4194,6 +4194,7 @@ angle::Result ContextVk::onImageWrite(VkImageAspectFlags aspectFlags,
image->changeLayout(aspectFlags, imageLayout, commandBuffer);
image->retain(&mResourceUseList);
image->onWrite();
return angle::Result::Continue;
}
......
......@@ -591,6 +591,7 @@ void CommandBufferHelper::imageWrite(vk::ResourceUseList *resourceUseList,
vk::ImageHelper *image)
{
image->retain(resourceUseList);
image->onWrite();
// Write always requires a barrier
PipelineStage barrierIndex = kImageMemoryBarrierData[imageLayout].barrierIndex;
ASSERT(barrierIndex != PipelineStage::InvalidEnum);
......@@ -2501,6 +2502,7 @@ void ImageHelper::resetCachedProperties()
mMaxLevel = 0;
mLayerCount = 0;
mLevelCount = 0;
mCurrentSingleClearValue.reset();
}
void ImageHelper::initStagingBuffer(RendererVk *renderer,
......@@ -2602,6 +2604,7 @@ void ImageHelper::releaseStagingBuffer(RendererVk *renderer)
}
mStagingBuffer.release(renderer);
mSubresourceUpdates.clear();
mCurrentSingleClearValue.reset();
}
void ImageHelper::resetImageWeakReference()
......@@ -3354,6 +3357,7 @@ void ImageHelper::removeSingleSubresourceStagedUpdates(ContextVk *contextVk,
index++;
}
}
mCurrentSingleClearValue.reset();
}
void ImageHelper::removeStagedUpdates(ContextVk *contextVk,
......@@ -4064,6 +4068,20 @@ angle::Result ImageHelper::flushStagedUpdates(ContextVk *contextVk,
removeSupersededUpdates(skipLevelsMask);
// If a clear is requested and we know it just has been cleared with the same value, we drop the
// clear
if (mSubresourceUpdates.size() == 1)
{
SubresourceUpdate &update = mSubresourceUpdates[0];
if (update.updateSource == UpdateSource::Clear && mCurrentSingleClearValue.valid() &&
mCurrentSingleClearValue.value() == update.clear)
{
update.release(contextVk->getRenderer());
mSubresourceUpdates.clear();
return angle::Result::Continue;
}
}
const uint32_t levelGLStart = levelVKStart + mBaseLevel;
const uint32_t levelGLEnd = levelVKEnd + mBaseLevel;
......@@ -4160,6 +4178,8 @@ angle::Result ImageHelper::flushStagedUpdates(ContextVk *contextVk,
ASSERT(updateMipLevelVK == update.clear.levelIndex);
clear(update.clear.aspectFlags, update.clear.value, updateMipLevelVK, updateBaseLayer,
updateLayerCount, commandBuffer);
// Remember the latest operation is a clear call
mCurrentSingleClearValue = update.clear;
}
else if (update.updateSource == UpdateSource::Buffer)
{
......@@ -4172,6 +4192,7 @@ angle::Result ImageHelper::flushStagedUpdates(ContextVk *contextVk,
commandBuffer->copyBufferToImage(currentBuffer->getBuffer().getHandle(), mImage,
getCurrentLayout(), 1, &update.buffer.copyRegion);
onWrite();
}
else
{
......@@ -4181,6 +4202,7 @@ angle::Result ImageHelper::flushStagedUpdates(ContextVk *contextVk,
commandBuffer->copyImage(update.image.image->getImage(),
update.image.image->getCurrentLayout(), mImage,
getCurrentLayout(), 1, &update.image.copyRegion);
onWrite();
}
update.release(contextVk->getRenderer());
......
......@@ -1386,6 +1386,8 @@ class ImageHelper final : public Resource, public angle::Subject
GLuint *inputDepthPitch,
GLuint *inputSkipBytes);
void onWrite() { mCurrentSingleClearValue.reset(); }
private:
enum class UpdateSource
{
......@@ -1393,14 +1395,20 @@ class ImageHelper final : public Resource, public angle::Subject
Buffer,
Image,
};
ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
struct ClearUpdate
{
bool operator==(const ClearUpdate &rhs)
{
return memcmp(this, &rhs, sizeof(ClearUpdate)) == 0;
}
VkImageAspectFlags aspectFlags;
VkClearValue value;
uint32_t levelIndex;
uint32_t layerIndex;
uint32_t layerCount;
};
ANGLE_DISABLE_STRUCT_PADDING_WARNINGS
struct BufferUpdate
{
BufferHelper *bufferHelper;
......@@ -1524,6 +1532,11 @@ class ImageHelper final : public Resource, public angle::Subject
// Staging buffer
DynamicBuffer mStagingBuffer;
std::vector<SubresourceUpdate> mSubresourceUpdates;
// Optimization for repeated clear with the same value. If this pointer is not null, the entire
// image it has been cleared to the specified clear value. If another clear call is made with
// the exact same clear value, we will detect and skip the clear call.
Optional<ClearUpdate> mCurrentSingleClearValue;
};
// A vector of image views, such as one per level or one per layer.
......
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