Commit 258d94f6 by Charlie Lao Committed by Commit Bot

Vulkan: Add workaround for nvidia to always merge barriers into one

vkCmdPipelineBarrier call Nvidia preferes one barrier call than multiple calls with fine grained stage dependency information. They do not care much about stage dependency. This adds a feature flag that sets to true on nvidia and will merge all barriers into one call. Bug: angleproject:4633 Change-Id: I204484aa4c5989655f74d70a0eaa235c3c83f548 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2207635 Commit-Queue: Charlie Lao <cclao@google.com> Reviewed-by: 's avatarCourtney Goeltzenleuchter <courtneygo@google.com>
parent 779a25a8
...@@ -308,6 +308,15 @@ struct FeaturesVk : FeatureSetBase ...@@ -308,6 +308,15 @@ struct FeaturesVk : FeatureSetBase
Feature supportDepthStencilRenderingFeedbackLoops = { Feature supportDepthStencilRenderingFeedbackLoops = {
"support_depth_stencil_rendering_feedback_loops", FeatureCategory::VulkanFeatures, "support_depth_stencil_rendering_feedback_loops", FeatureCategory::VulkanFeatures,
"Suport depth/stencil rendering feedback loops", &members, "http://anglebug.com/4490"}; "Suport depth/stencil rendering feedback loops", &members, "http://anglebug.com/4490"};
// Desktop (at least NVIDIA) drivers prefer combining barriers into one vkCmdPipelineBarrier
// call over issuing multiple barrier calls with fine grained dependency information to have
// better performance. http://anglebug.com/4633
Feature preferAggregateBarrierCalls = {
"prefer_aggregate_barrier_calls", FeatureCategory::VulkanWorkarounds,
"Single barrier call is preferred over multiple calls with "
"fine grained pipeline stage dependency information",
&members, "http://anglebug.com/4633"};
}; };
inline FeaturesVk::FeaturesVk() = default; inline FeaturesVk::FeaturesVk() = default;
......
...@@ -640,8 +640,9 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk ...@@ -640,8 +640,9 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
mEmulateSeamfulCubeMapSampling(false), mEmulateSeamfulCubeMapSampling(false),
mUseOldRewriteStructSamplers(false), mUseOldRewriteStructSamplers(false),
mPoolAllocator(kDefaultPoolAllocatorPageSize, 1), mPoolAllocator(kDefaultPoolAllocatorPageSize, 1),
mOutsideRenderPassCommands(false), mOutsideRenderPassCommands(false,
mRenderPassCommands(true), renderer->getFeatures().preferAggregateBarrierCalls.enabled),
mRenderPassCommands(true, renderer->getFeatures().preferAggregateBarrierCalls.enabled),
mHasPrimaryCommands(false), mHasPrimaryCommands(false),
mGpuEventsEnabled(false), mGpuEventsEnabled(false),
mGpuClockSync{std::numeric_limits<double>::max(), std::numeric_limits<double>::max()}, mGpuClockSync{std::numeric_limits<double>::max(), std::numeric_limits<double>::max()},
......
...@@ -1693,6 +1693,8 @@ void RendererVk::initFeatures(DisplayVk *displayVk, const ExtensionNameList &dev ...@@ -1693,6 +1693,8 @@ void RendererVk::initFeatures(DisplayVk *displayVk, const ExtensionNameList &dev
ANGLE_FEATURE_CONDITION(&mFeatures, supportDepthStencilRenderingFeedbackLoops, true); ANGLE_FEATURE_CONDITION(&mFeatures, supportDepthStencilRenderingFeedbackLoops, true);
ANGLE_FEATURE_CONDITION(&mFeatures, preferAggregateBarrierCalls, !IsAndroid());
angle::PlatformMethods *platform = ANGLEPlatformCurrent(); angle::PlatformMethods *platform = ANGLEPlatformCurrent();
platform->overrideFeaturesVk(platform, &mFeatures); platform->overrideFeaturesVk(platform, &mFeatures);
......
...@@ -511,7 +511,7 @@ VkImageLayout ConvertImageLayoutToVkImageLayout(ImageLayout imageLayout) ...@@ -511,7 +511,7 @@ VkImageLayout ConvertImageLayoutToVkImageLayout(ImageLayout imageLayout)
} }
// CommandBufferHelper implementation. // CommandBufferHelper implementation.
CommandBufferHelper::CommandBufferHelper(bool hasRenderPass) CommandBufferHelper::CommandBufferHelper(bool hasRenderPass, bool mergeBarriers)
: mPipelineBarriers(), : mPipelineBarriers(),
mPipelineBarrierMask(), mPipelineBarrierMask(),
mCounter(0), mCounter(0),
...@@ -520,7 +520,8 @@ CommandBufferHelper::CommandBufferHelper(bool hasRenderPass) ...@@ -520,7 +520,8 @@ CommandBufferHelper::CommandBufferHelper(bool hasRenderPass)
mTransformFeedbackCounterBuffers{}, mTransformFeedbackCounterBuffers{},
mValidTransformFeedbackBufferCount(0), mValidTransformFeedbackBufferCount(0),
mRebindTransformFeedbackBuffers(false), mRebindTransformFeedbackBuffers(false),
mIsRenderPassCommandBuffer(hasRenderPass) mIsRenderPassCommandBuffer(hasRenderPass),
mMergeBarriers(mergeBarriers)
{} {}
CommandBufferHelper::~CommandBufferHelper() CommandBufferHelper::~CommandBufferHelper()
...@@ -591,15 +592,30 @@ void CommandBufferHelper::imageWrite(vk::ResourceUseList *resourceUseList, ...@@ -591,15 +592,30 @@ void CommandBufferHelper::imageWrite(vk::ResourceUseList *resourceUseList,
void CommandBufferHelper::executeBarriers(vk::PrimaryCommandBuffer *primary) void CommandBufferHelper::executeBarriers(vk::PrimaryCommandBuffer *primary)
{ {
if (!mPipelineBarrierMask.any()) // make a local copy for faster access
PipelineStagesMask mask = mPipelineBarrierMask;
if (mask.none())
{ {
return; return;
} }
for (PipelineStage pipelineStage : mPipelineBarrierMask) if (mMergeBarriers)
{ {
PipelineBarrier &barrier = mPipelineBarriers[pipelineStage]; PipelineStagesMask::Iterator iter = mask.begin();
barrier.writeCommand(primary); PipelineBarrier &barrier = mPipelineBarriers[*iter];
for (++iter; iter != mask.end(); ++iter)
{
barrier.merge(&mPipelineBarriers[*iter]);
}
barrier.execute(primary);
}
else
{
for (PipelineStage pipelineStage : mask)
{
PipelineBarrier &barrier = mPipelineBarriers[pipelineStage];
barrier.execute(primary);
}
} }
mPipelineBarrierMask.reset(); mPipelineBarrierMask.reset();
} }
......
...@@ -600,7 +600,7 @@ class PipelineBarrier : angle::NonCopyable ...@@ -600,7 +600,7 @@ class PipelineBarrier : angle::NonCopyable
bool isEmpty() const { return mImageMemoryBarriers.empty() && mMemoryBarrierSrcAccess == 0; } bool isEmpty() const { return mImageMemoryBarriers.empty() && mMemoryBarrierSrcAccess == 0; }
void writeCommand(PrimaryCommandBuffer *primary) void execute(PrimaryCommandBuffer *primary)
{ {
if (isEmpty()) if (isEmpty())
{ {
...@@ -823,7 +823,7 @@ class BufferHelper final : public Resource ...@@ -823,7 +823,7 @@ class BufferHelper final : public Resource
struct CommandBufferHelper : angle::NonCopyable struct CommandBufferHelper : angle::NonCopyable
{ {
public: public:
CommandBufferHelper(bool canHaveRenderPass); CommandBufferHelper(bool canHaveRenderPass, bool mergeBarriers);
~CommandBufferHelper(); ~CommandBufferHelper();
// General Functions (non-renderPass specific) // General Functions (non-renderPass specific)
...@@ -950,6 +950,7 @@ struct CommandBufferHelper : angle::NonCopyable ...@@ -950,6 +950,7 @@ struct CommandBufferHelper : angle::NonCopyable
bool mRebindTransformFeedbackBuffers; bool mRebindTransformFeedbackBuffers;
const bool mIsRenderPassCommandBuffer; const bool mIsRenderPassCommandBuffer;
const bool mMergeBarriers;
}; };
// Imagine an image going through a few layout transitions: // Imagine an image going through a few layout transitions:
......
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