Commit 97d10f2b authored by Khushal's avatar Khushal Committed by Commit Bot

gpu: Ensure RingBuffer maintains aligned memory offsets.

When requesting a buffer for OOP raster, the client requests the
largest free size for which no tokens are pending, and can be allocated
without waiting. This is queried from RingBuffer::GetLargestFreeSize.
However, since this size is rounded up to the next alignment when making
the allocation, this results in synchronously waiting on tokens to make
room for the extra padding.

Ensure that ShrinkLastBlock rounds up the new size for the block so
the buffer always has memory aligned free size.

R=enne@chromium.org, piman@chromium.org

Bug: 803925
Cq-Include-Trybots: master.tryserver.chromium.android:android_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_optional_gpu_tests_rel;master.tryserver.chromium.mac:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel
Change-Id: Iff1286b6f412f126dbf33300387f85f9c21e91ed
Reviewed-on: https://chromium-review.googlesource.com/922445
Commit-Queue: Khushal <khushalsagar@chromium.org>
Reviewed-by: default avatarenne <enne@chromium.org>
Reviewed-by: default avatarAntoine Labour <piman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#537250}
parent 885dd799
......@@ -66,7 +66,7 @@ void* RingBuffer::Alloc(unsigned int size) {
size = RoundToAlignment(size);
// Wait until there is enough room.
while (size > GetLargestFreeSizeNoWaiting()) {
while (size > GetLargestFreeSizeNoWaitingInternal()) {
FreeOldestBlock();
}
......@@ -145,6 +145,12 @@ void RingBuffer::DiscardBlock(void* pointer) {
}
unsigned int RingBuffer::GetLargestFreeSizeNoWaiting() {
unsigned int size = GetLargestFreeSizeNoWaitingInternal();
DCHECK_EQ(size, RoundToAlignment(size));
return size;
}
unsigned int RingBuffer::GetLargestFreeSizeNoWaitingInternal() {
while (!blocks_.empty()) {
Block& block = blocks_.front();
if (!helper_->HasTokenPassed(block.token) || block.state == IN_USE) break;
......@@ -169,7 +175,7 @@ unsigned int RingBuffer::GetLargestFreeSizeNoWaiting() {
}
unsigned int RingBuffer::GetTotalFreeSizeNoWaiting() {
unsigned int largest_free_size = GetLargestFreeSizeNoWaiting();
unsigned int largest_free_size = GetLargestFreeSizeNoWaitingInternal();
if (free_offset_ > in_use_offset_) {
// It's free from free_offset_ to size_ and from 0 to in_use_offset_.
return size_ - free_offset_ + in_use_offset_;
......@@ -188,6 +194,9 @@ void RingBuffer::ShrinkLastBlock(unsigned int new_size) {
// Can't shrink to size 0, see comments in Alloc.
new_size = std::max(new_size, 1u);
// Allocate rounded to alignment size so that the offsets are always
// memory-aligned.
new_size = RoundToAlignment(new_size);
free_offset_ = block.offset + new_size;
block.size = new_size;
}
......
......@@ -120,6 +120,7 @@ class GPU_EXPORT RingBuffer {
using BlockIndex = unsigned int;
void FreeOldestBlock();
unsigned int GetLargestFreeSizeNoWaitingInternal();
CommandBufferHelper* helper_;
......
......@@ -419,4 +419,13 @@ TEST_F(RingBufferTest, DiscardAllPaddingFromBeginningTest) {
EXPECT_EQ(kAlloc1 + kAlloc2, allocator_->GetLargestFreeSizeNoWaiting());
}
TEST_F(RingBufferTest, LargestFreeSizeNoWaiting) {
// GetLargestFreeSizeNoWaiting should return the largest free aligned size.
void* ptr = allocator_->Alloc(kBufferSize);
EXPECT_EQ(0u, allocator_->GetLargestFreeSizeNoWaiting());
allocator_->ShrinkLastBlock(kBufferSize - 2 * kAlignment - 1);
EXPECT_EQ(2 * kAlignment, allocator_->GetLargestFreeSizeNoWaiting());
allocator_->FreePendingToken(ptr, helper_.get()->InsertToken());
}
} // namespace gpu
......@@ -527,20 +527,20 @@ TEST_F(TransferBufferExpandContractTest, Shrink) {
EXPECT_EQ(0u, transfer_buffer_->GetFreeSize());
// Shrink once.
const unsigned int shrink_size1 = 80;
const unsigned int shrink_size1 = 64;
EXPECT_LT(shrink_size1, alloc_size);
transfer_buffer_->ShrinkLastBlock(shrink_size1);
transfer_buffer_->ShrinkLastBlock(shrink_size1 - kAlignment + 1);
EXPECT_EQ(alloc_size - shrink_size1, transfer_buffer_->GetFreeSize());
// Shrink again.
const unsigned int shrink_size2 = 30;
const unsigned int shrink_size2 = 32;
EXPECT_LT(shrink_size2, shrink_size1);
transfer_buffer_->ShrinkLastBlock(shrink_size2);
EXPECT_EQ(alloc_size - shrink_size2, transfer_buffer_->GetFreeSize());
// Shrink to zero (minimum size is 1).
// Shrink to zero (minimum size is kAlignment).
transfer_buffer_->ShrinkLastBlock(0);
EXPECT_EQ(alloc_size - 1, transfer_buffer_->GetFreeSize());
EXPECT_EQ(alloc_size - kAlignment, transfer_buffer_->GetFreeSize());
transfer_buffer_->FreePendingToken(ptr, 1);
}
......
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