Commit dcfaac01 authored by James Darpinian's avatar James Darpinian Committed by Commit Bot

GPU: Remove transfer buffer autoflushing.

This is change #2 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 transfer buffer would flush the command buffer after an
arbitrary number of bytes were sent. This change removes that threshold.
Any performance benefit of early flushing is killed by the additional
context switching.

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: I8f71668d4b976332820d290868282d41286ab4fe
Reviewed-on: https://chromium-review.googlesource.com/1077568
Commit-Queue: James Darpinian <jdarpinian@chromium.org>
Reviewed-by: default avatarAntoine Labour <piman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#563404}
parent dbf25685
......@@ -156,7 +156,7 @@ gpu::ContextResult ImplementationBase::Initialize(
if (!transfer_buffer_->Initialize(
limits.start_transfer_buffer_size, kStartingOffset,
limits.min_transfer_buffer_size, limits.max_transfer_buffer_size,
kAlignment, kSizeToFlush)) {
kAlignment)) {
// TransferBuffer::Initialize doesn't fail for transient reasons such as if
// the context was lost. See http://crrev.com/c/720269
LOG(ERROR) << "ContextResult::kFatalFailure: "
......
......@@ -51,9 +51,6 @@ class GLES2_IMPL_EXPORT ImplementationBase
// used for testing only. If more things are reseved add them here.
static const unsigned int kStartingOffset = kMaxSizeOfSimpleResult;
// Size in bytes to issue async flush for transfer buffer.
static const unsigned int kSizeToFlush = 256 * 1024;
// Alignment of allocations.
static const unsigned int kAlignment = 16;
......
......@@ -44,8 +44,7 @@ bool MockTransferBuffer::Initialize(unsigned int starting_buffer_size,
unsigned int result_size,
unsigned int /* min_buffer_size */,
unsigned int /* max_buffer_size */,
unsigned int alignment,
unsigned int /* size_to_flush */) {
unsigned int alignment) {
// Just check they match.
return size_ == starting_buffer_size && result_size_ == result_size &&
alignment_ == alignment && !initialize_fail_;
......
......@@ -35,8 +35,7 @@ class MockTransferBuffer : public TransferBufferInterface {
unsigned int result_size,
unsigned int /* min_buffer_size */,
unsigned int /* max_buffer_size */,
unsigned int alignment,
unsigned int size_to_flush) override;
unsigned int alignment) override;
int GetShmId() override;
void* GetResultBuffer() override;
int GetResultOffset() override;
......
......@@ -25,8 +25,6 @@ TransferBuffer::TransferBuffer(
min_buffer_size_(0),
max_buffer_size_(0),
alignment_(0),
size_to_flush_(0),
bytes_since_last_flush_(0),
buffer_id_(-1),
result_buffer_(NULL),
result_shm_offset_(0),
......@@ -45,19 +43,16 @@ base::SharedMemoryHandle TransferBuffer::shared_memory_handle() const {
return buffer_->backing()->shared_memory_handle();
}
bool TransferBuffer::Initialize(
unsigned int default_buffer_size,
unsigned int result_size,
unsigned int min_buffer_size,
unsigned int max_buffer_size,
unsigned int alignment,
unsigned int size_to_flush) {
bool TransferBuffer::Initialize(unsigned int default_buffer_size,
unsigned int result_size,
unsigned int min_buffer_size,
unsigned int max_buffer_size,
unsigned int alignment) {
result_size_ = result_size;
default_buffer_size_ = default_buffer_size;
min_buffer_size_ = min_buffer_size;
max_buffer_size_ = max_buffer_size;
alignment_ = alignment;
size_to_flush_ = size_to_flush;
ReallocateRingBuffer(default_buffer_size_ - result_size);
return HaveBuffer();
}
......@@ -72,7 +67,6 @@ void TransferBuffer::Free() {
result_buffer_ = NULL;
result_shm_offset_ = 0;
ring_buffer_.reset();
bytes_since_last_flush_ = 0;
}
}
......@@ -91,10 +85,6 @@ void TransferBuffer::DiscardBlock(void* p) {
void TransferBuffer::FreePendingToken(void* p, unsigned int token) {
ring_buffer_->FreePendingToken(p, token);
if (bytes_since_last_flush_ >= size_to_flush_ && size_to_flush_ > 0) {
helper_->Flush();
bytes_since_last_flush_ = 0;
}
}
unsigned int TransferBuffer::GetSize() const {
......@@ -168,7 +158,6 @@ void* TransferBuffer::AllocUpTo(
unsigned int max_size = ring_buffer_->GetLargestFreeOrPendingSize();
*size_allocated = std::min(max_size, size);
bytes_since_last_flush_ += *size_allocated;
return ring_buffer_->Alloc(*size_allocated);
}
......@@ -184,7 +173,6 @@ void* TransferBuffer::Alloc(unsigned int size) {
return NULL;
}
bytes_since_last_flush_ += size;
return ring_buffer_->Alloc(size);
}
......
......@@ -36,13 +36,11 @@ class GPU_EXPORT TransferBufferInterface {
// Otherwise, this returns an invalid handle.
virtual base::SharedMemoryHandle shared_memory_handle() const = 0;
virtual bool Initialize(
unsigned int buffer_size,
unsigned int result_size,
unsigned int min_buffer_size,
unsigned int max_buffer_size,
unsigned int alignment,
unsigned int size_to_flush) = 0;
virtual bool Initialize(unsigned int buffer_size,
unsigned int result_size,
unsigned int min_buffer_size,
unsigned int max_buffer_size,
unsigned int alignment) = 0;
virtual int GetShmId() = 0;
virtual void* GetResultBuffer() = 0;
......@@ -86,8 +84,7 @@ class GPU_EXPORT TransferBuffer : public TransferBufferInterface {
unsigned int result_size,
unsigned int min_buffer_size,
unsigned int max_buffer_size,
unsigned int alignment,
unsigned int size_to_flush) override;
unsigned int alignment) override;
int GetShmId() override;
void* GetResultBuffer() override;
int GetResultOffset() override;
......@@ -131,12 +128,6 @@ class GPU_EXPORT TransferBuffer : public TransferBufferInterface {
// alignment for allocations
unsigned int alignment_;
// Size at which to do an async flush. 0 = never.
unsigned int size_to_flush_;
// Number of bytes since we last flushed.
unsigned int bytes_since_last_flush_;
// the current buffer.
scoped_refptr<gpu::Buffer> buffer_;
......
......@@ -44,14 +44,10 @@ class TransferBufferTest : public testing::Test {
void SetUp() override;
void TearDown() override;
virtual void Initialize(unsigned int size_to_flush) {
virtual void Initialize() {
ASSERT_TRUE(transfer_buffer_->Initialize(
kTransferBufferSize,
kStartingOffset,
kTransferBufferSize,
kTransferBufferSize,
kAlignment,
size_to_flush));
kTransferBufferSize, kStartingOffset, kTransferBufferSize,
kTransferBufferSize, kAlignment));
}
MockClientCommandBufferMockFlush* command_buffer() const {
......@@ -101,7 +97,7 @@ const size_t TransferBufferTest::kTransferBufferSize;
#endif
TEST_F(TransferBufferTest, Basic) {
Initialize(0);
Initialize();
EXPECT_TRUE(transfer_buffer_->HaveBuffer());
EXPECT_EQ(transfer_buffer_id_, transfer_buffer_->GetShmId());
EXPECT_EQ(
......@@ -112,7 +108,7 @@ TEST_F(TransferBufferTest, Basic) {
}
TEST_F(TransferBufferTest, Free) {
Initialize(0);
Initialize();
EXPECT_TRUE(transfer_buffer_->HaveBuffer());
EXPECT_EQ(transfer_buffer_id_, transfer_buffer_->GetShmId());
EXPECT_NE(base::UnguessableToken(),
......@@ -204,7 +200,7 @@ TEST_F(TransferBufferTest, Free) {
}
TEST_F(TransferBufferTest, TooLargeAllocation) {
Initialize(0);
Initialize();
// Check that we can't allocate large than max size.
void* ptr = transfer_buffer_->Alloc(kTransferBufferSize + 1);
EXPECT_TRUE(ptr == NULL);
......@@ -218,7 +214,7 @@ TEST_F(TransferBufferTest, TooLargeAllocation) {
}
TEST_F(TransferBufferTest, MemoryAlignmentAfterZeroAllocation) {
Initialize(32u);
Initialize();
void* ptr = transfer_buffer_->Alloc(0);
EXPECT_EQ((reinterpret_cast<uintptr_t>(ptr) & (kAlignment - 1)), 0u);
transfer_buffer_->FreePendingToken(ptr, helper_->InsertToken());
......@@ -228,32 +224,6 @@ TEST_F(TransferBufferTest, MemoryAlignmentAfterZeroAllocation) {
transfer_buffer_->FreePendingToken(ptr, helper_->InsertToken());
}
TEST_F(TransferBufferTest, Flush) {
Initialize(16u);
unsigned int size_allocated = 0;
for (int i = 0; i < 8; ++i) {
void* ptr = transfer_buffer_->AllocUpTo(8u, &size_allocated);
ASSERT_TRUE(ptr != NULL);
EXPECT_EQ(8u, size_allocated);
if (i % 2) {
EXPECT_CALL(*command_buffer(), Flush(_))
.Times(1)
.RetiresOnSaturation();
}
transfer_buffer_->FreePendingToken(ptr, helper_->InsertToken());
}
for (int i = 0; i < 8; ++i) {
void* ptr = transfer_buffer_->Alloc(8u);
ASSERT_TRUE(ptr != NULL);
if (i % 2) {
EXPECT_CALL(*command_buffer(), Flush(_))
.Times(1)
.RetiresOnSaturation();
}
transfer_buffer_->FreePendingToken(ptr, helper_->InsertToken());
}
}
class MockClientCommandBufferCanFail : public MockClientCommandBufferMockFlush {
public:
MockClientCommandBufferCanFail() = default;
......@@ -321,12 +291,8 @@ void TransferBufferExpandContractTest::SetUp() {
transfer_buffer_.reset(new TransferBuffer(helper_.get()));
ASSERT_TRUE(transfer_buffer_->Initialize(
kStartTransferBufferSize,
kStartingOffset,
kMinTransferBufferSize,
kMaxTransferBufferSize,
kAlignment,
0));
kStartTransferBufferSize, kStartingOffset, kMinTransferBufferSize,
kMaxTransferBufferSize, kAlignment));
}
void TransferBufferExpandContractTest::TearDown() {
......
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