зеркало из https://github.com/AvaloniaUI/angle.git
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:
Родитель
a52834d818
Коммит
34eb401ba5
|
@ -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.
|
||||
|
|
Загрузка…
Ссылка в новой задаче