Vulkan: Optimize Attribute Change Perf (2/5)

This patch series optimizes programs that use the pattern:

for (;;) {
  glVertexAttribPointer(...)
  glDraw(...)
}

Change 2: Micro-optimize XFB resume CPU overhead.

We don't need to set resume on every new command buffer. We only need
to set the dirty bit when we have an unexpected pause.

In total the patch series reduces test iteration time by 25%.

Test: DrawCallPerfBenchmark.Run/vulkan_attrib_change
Bug: angleproject:5045
Bug: b/168493024
Change-Id: I8f6c68ff0513be4f405276e395d80bc1a185a061
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2409174
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Tim Van Patten <timvp@google.com>
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
This commit is contained in:
Jamie Madill 2020-09-16 21:44:56 -04:00 коммит произвёл Commit Bot
Родитель 9b4cfd1883
Коммит 357caadb09
5 изменённых файлов: 48 добавлений и 39 удалений

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

@ -694,16 +694,6 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS);
mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_SHADER_RESOURCES);
if (getFeatures().supportsTransformFeedbackExtension.enabled ||
getFeatures().emulateTransformFeedback.enabled)
{
mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS);
}
if (getFeatures().supportsTransformFeedbackExtension.enabled)
{
mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_STATE);
mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME);
}
mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS_BINDING);
@ -713,12 +703,6 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
mNewComputeCommandBufferDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
mNewComputeCommandBufferDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS_BINDING);
mNewGraphicsPipelineDirtyBits.set(DIRTY_BIT_PIPELINE);
if (getFeatures().supportsTransformFeedbackExtension.enabled)
{
mNewGraphicsPipelineDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME);
}
mGraphicsDirtyBitHandlers[DIRTY_BIT_DEFAULT_ATTRIBS] =
&ContextVk::handleDirtyGraphicsDefaultAttribs;
mGraphicsDirtyBitHandlers[DIRTY_BIT_PIPELINE] = &ContextVk::handleDirtyGraphicsPipeline;
@ -1354,7 +1338,9 @@ angle::Result ContextVk::handleDirtyGraphicsPipeline(const gl::Context *context,
mGraphicsPipelineTransition.reset();
}
mRenderPassCommands->pauseTransformFeedbackIfStarted();
resumeTransformFeedbackIfStarted();
commandBuffer->bindGraphicsPipeline(mCurrentGraphicsPipeline->getPipeline());
// Update the queue serial for the pipeline object.
ASSERT(mCurrentGraphicsPipeline && mCurrentGraphicsPipeline->valid());
@ -1646,7 +1632,10 @@ angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackResume(
const gl::Context *context,
vk::CommandBuffer *commandBuffer)
{
mRenderPassCommands->resumeTransformFeedbackIfStarted();
if (mRenderPassCommands->isTransformFeedbackStarted())
{
mRenderPassCommands->resumeTransformFeedback();
}
return angle::Result::Continue;
}
@ -3194,6 +3183,17 @@ angle::Result ContextVk::onMakeCurrent(const gl::Context *context)
updateSurfaceRotationReadFramebuffer(glState);
invalidateDriverUniforms();
const gl::ProgramExecutable *executable = mState.getProgramExecutable();
if (executable && executable->hasTransformFeedbackOutput() &&
mState.isTransformFeedbackActive())
{
onTransformFeedbackStateChanged();
if (getFeatures().supportsTransformFeedbackExtension.enabled)
{
mGraphicsDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME);
}
}
return angle::Result::Continue;
}
@ -3442,7 +3442,7 @@ void ContextVk::onTransformFeedbackStateChanged()
if (getFeatures().supportsTransformFeedbackExtension.enabled)
{
mGraphicsDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_STATE);
invalidateCurrentTransformFeedbackBuffers();
mGraphicsDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS);
}
else if (getFeatures().emulateTransformFeedback.enabled)
{
@ -3492,7 +3492,10 @@ void ContextVk::onEndTransformFeedback()
{
if (getFeatures().supportsTransformFeedbackExtension.enabled)
{
mRenderPassCommands->endTransformFeedback();
if (mRenderPassCommands->isTransformFeedbackStarted())
{
mRenderPassCommands->endTransformFeedback();
}
}
else if (getFeatures().emulateTransformFeedback.enabled)
{
@ -3508,6 +3511,7 @@ angle::Result ContextVk::onPauseTransformFeedback()
}
else if (getFeatures().emulateTransformFeedback.enabled)
{
invalidateCurrentTransformFeedbackBuffers();
return flushCommandsAndEndRenderPass();
}
return angle::Result::Continue;
@ -3676,6 +3680,16 @@ void ContextVk::writeAtomicCounterBufferDriverUniformOffsets(uint32_t *offsetsOu
}
}
ANGLE_INLINE void ContextVk::resumeTransformFeedbackIfStarted()
{
if (mRenderPassCommands->isTransformFeedbackStarted())
{
ASSERT(getFeatures().supportsTransformFeedbackExtension.enabled);
mGraphicsDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME);
mRenderPassCommands->pauseTransformFeedback();
}
}
angle::Result ContextVk::handleDirtyGraphicsDriverUniforms(const gl::Context *context,
vk::CommandBuffer *commandBuffer)
{
@ -4664,6 +4678,8 @@ angle::Result ContextVk::flushCommandsAndEndRenderPass()
addOverlayUsedBuffersCount(mRenderPassCommands);
resumeTransformFeedbackIfStarted();
mRenderPassCommands->endRenderPass(this);
if (mRenderer->getFeatures().enableCommandProcessingThread.enabled)

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

@ -795,7 +795,7 @@ class ContextVk : public ContextImpl, public vk::Context
ANGLE_INLINE void invalidateCurrentGraphicsPipeline()
{
mGraphicsDirtyBits |= mNewGraphicsPipelineDirtyBits;
mGraphicsDirtyBits.set(DIRTY_BIT_PIPELINE);
}
ANGLE_INLINE void invalidateCurrentComputePipeline()
@ -919,6 +919,7 @@ class ContextVk : public ContextImpl, public vk::Context
void populateTransformFeedbackBufferSet(
size_t bufferCount,
const gl::TransformFeedbackBuffersArray<vk::BufferHelper *> &buffers);
void resumeTransformFeedbackIfStarted();
// DescriptorSet writes
template <typename T, const T *VkWriteDescriptorSet::*pInfo>
@ -964,7 +965,6 @@ class ContextVk : public ContextImpl, public vk::Context
DirtyBits mIndexedDirtyBitsMask;
DirtyBits mNewGraphicsCommandBufferDirtyBits;
DirtyBits mNewComputeCommandBufferDirtyBits;
DirtyBits mNewGraphicsPipelineDirtyBits;
// Cached back-end objects.
VertexArrayVk *mVertexArray;

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

@ -898,8 +898,6 @@ void CommandBufferHelper::restartRenderPassWithReadOnlyDepth(const Framebuffer &
void CommandBufferHelper::endRenderPass(ContextVk *contextVk)
{
pauseTransformFeedbackIfStarted();
if (mDepthStencilAttachmentIndex == kAttachmentIndexInvalid)
{
return;
@ -965,7 +963,7 @@ void CommandBufferHelper::beginTransformFeedback(size_t validBufferCount,
void CommandBufferHelper::endTransformFeedback()
{
ASSERT(mIsRenderPassCommandBuffer);
pauseTransformFeedbackIfStarted();
pauseTransformFeedback();
mValidTransformFeedbackBufferCount = 0;
}
@ -1164,13 +1162,10 @@ void CommandBufferHelper::releaseToContextQueue(ContextVk *contextVk)
contextVk->recycleCommandBuffer(this);
}
void CommandBufferHelper::resumeTransformFeedbackIfStarted()
void CommandBufferHelper::resumeTransformFeedback()
{
ASSERT(mIsRenderPassCommandBuffer);
if (mValidTransformFeedbackBufferCount == 0)
{
return;
}
ASSERT(isTransformFeedbackStarted());
uint32_t numCounterBuffers =
mRebindTransformFeedbackBuffers ? 0 : mValidTransformFeedbackBufferCount;
@ -1181,14 +1176,10 @@ void CommandBufferHelper::resumeTransformFeedbackIfStarted()
mTransformFeedbackCounterBuffers.data());
}
void CommandBufferHelper::pauseTransformFeedbackIfStarted()
void CommandBufferHelper::pauseTransformFeedback()
{
ASSERT(mIsRenderPassCommandBuffer);
if (mValidTransformFeedbackBufferCount == 0)
{
return;
}
ASSERT(isTransformFeedbackStarted());
mCommandBuffer.endTransformFeedback(mValidTransformFeedbackBufferCount,
mTransformFeedbackCounterBuffers.data());
}

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

@ -1047,8 +1047,9 @@ class CommandBufferHelper : angle::NonCopyable
return mRenderArea;
}
void resumeTransformFeedbackIfStarted();
void pauseTransformFeedbackIfStarted();
void resumeTransformFeedback();
void pauseTransformFeedback();
bool isTransformFeedbackStarted() const { return mValidTransformFeedbackBufferCount > 0; }
uint32_t getAndResetCounter()
{

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

@ -582,7 +582,8 @@ TEST_P(TransformFeedbackTest, MultiContext)
GLuint buffer;
size_t primitiveCounts[passCount];
};
ContextInfo contexts[32];
static constexpr uint32_t kContextCount = 32;
ContextInfo contexts[kContextCount];
const size_t maxDrawSize = 512;