Commit 62ca13ce authored by James Darpinian's avatar James Darpinian Committed by Commit Bot

GPU: Make command buffer autoflush more conservative.

This is change #1 of 3 reducing context switching during WebGL
rendering. On tiled rendering GPUs context switches are slow and can
even cause multisampling artifacts. Every time the command buffer is
flushed, a context switch is possible.

Before, the command buffer helper would always autoflush eventually if
no explicit flush was received. Commands would accumulate across
multiple frames until the autoflush threshold was reached. Implicit
flushes caused by ordering barriers were not taken into account.

Now the autoflush decision is based on the last ordering barrier instead
of the last explicit flush. Since there's an ordering barrier at least
once a frame, autoflush will only happen if the threshold is reached
within a single frame.

Bug: 828363,835353
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel
Change-Id: I168be6892620b1813c598a912e59147f9c45896f
Reviewed-on: https://chromium-review.googlesource.com/1077435Reviewed-by: default avatarSunny Sachanandani <sunnyps@chromium.org>
Reviewed-by: default avatarAntoine Labour <piman@chromium.org>
Commit-Queue: James Darpinian <jdarpinian@chromium.org>
Cr-Commit-Position: refs/heads/master@{#563149}
parent 3bee3633
...@@ -62,8 +62,8 @@ void CommandBufferHelper::CalcImmediateEntries(int waiting_count) { ...@@ -62,8 +62,8 @@ void CommandBufferHelper::CalcImmediateEntries(int waiting_count) {
total_entry_count_ / total_entry_count_ /
((curr_get == last_flush_put_) ? kAutoFlushSmall : kAutoFlushBig); ((curr_get == last_flush_put_) ? kAutoFlushSmall : kAutoFlushBig);
int32_t pending = int32_t pending = (put_ + total_entry_count_ - last_ordering_barrier_put_) %
(put_ + total_entry_count_ - last_flush_put_) % total_entry_count_; total_entry_count_;
if (pending > 0 && pending >= limit) { if (pending > 0 && pending >= limit) {
// Time to force flush. // Time to force flush.
...@@ -315,7 +315,14 @@ void CommandBufferHelper::WaitForAvailableEntries(int32_t count) { ...@@ -315,7 +315,14 @@ void CommandBufferHelper::WaitForAvailableEntries(int32_t count) {
// Try to get 'count' entries without flushing. // Try to get 'count' entries without flushing.
CalcImmediateEntries(count); CalcImmediateEntries(count);
if (immediate_entry_count_ < count) { if (immediate_entry_count_ < count) {
// Try again with a shallow Flush(). // Update cached_get_offset_ and try again.
UpdateCachedState(command_buffer_->GetLastState());
CalcImmediateEntries(count);
}
if (immediate_entry_count_ < count) {
// Try again with a shallow Flush(). Flush can change immediate_entry_count_
// because of the auto flush logic.
FlushLazy(); FlushLazy();
CalcImmediateEntries(count); CalcImmediateEntries(count);
if (immediate_entry_count_ < count) { if (immediate_entry_count_ < count) {
......
...@@ -334,6 +334,34 @@ TEST_F(CommandBufferHelperTest, TestCalcImmediateEntriesAutoFlushing) { ...@@ -334,6 +334,34 @@ TEST_F(CommandBufferHelperTest, TestCalcImmediateEntriesAutoFlushing) {
EXPECT_EQ(error::kNoError, GetError()); EXPECT_EQ(error::kNoError, GetError());
} }
// Checks that automatic flushing treats ordering barriers as flushes.
TEST_F(CommandBufferHelperTest,
TestCalcImmediateEntriesAutoFlushingOrderingBarrier) {
// Check that auto flush happens without an ordering barrier.
AddUniqueCommandWithExpect(error::kNoError, kAutoFlushSmall - 1);
EXPECT_EQ(0, command_buffer_->FlushCount());
AddUniqueCommandWithExpect(error::kNoError, 1);
// Auto flush should be triggered by going past the threshold.
EXPECT_EQ(1, command_buffer_->FlushCount());
helper_->Finish();
EXPECT_EQ(2, command_buffer_->FlushCount());
// Check that an ordering barrier prevents auto flush.
AddUniqueCommandWithExpect(error::kNoError, kAutoFlushSmall - 1);
EXPECT_EQ(2, command_buffer_->FlushCount());
helper_->OrderingBarrier();
EXPECT_EQ(3, command_buffer_->FlushCount());
AddUniqueCommandWithExpect(error::kNoError, 1);
// Adding a command should not have caused a flush because there was an
// ordering barrier.
EXPECT_EQ(3, command_buffer_->FlushCount());
// Check that the commands did happen.
helper_->Finish();
Mock::VerifyAndClearExpectations(api_mock_.get());
EXPECT_EQ(error::kNoError, GetError());
}
// Checks immediate_entry_count_ calc when automatic flushing is enabled, and // Checks immediate_entry_count_ calc when automatic flushing is enabled, and
// we allocate commands over the immediate_entry_count_ size. // we allocate commands over the immediate_entry_count_ size.
TEST_F(CommandBufferHelperTest, TestCalcImmediateEntriesOverFlushLimit) { TEST_F(CommandBufferHelperTest, TestCalcImmediateEntriesOverFlushLimit) {
......
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