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/+/2255643
Reviewed-by: Tim Van Patten <timvp@google.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Charlie Lao <cclao@google.com>
This commit is contained in:
Charlie Lao 2020-06-19 15:36:18 -07:00 коммит произвёл Commit Bot
Родитель a52834d818
Коммит 34eb401ba5
3 изменённых файлов: 36 добавлений и 0 удалений

Просмотреть файл

@ -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.