Skip to content

Commit

Permalink
Make transferbuffer increase in size dynamically
Browse files Browse the repository at this point in the history
TEST=unit tests
BUG=101431


Review URL: http://codereview.chromium.org/9113069

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@119430 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
gman@chromium.org committed Jan 27, 2012
1 parent 52fe647 commit d5c7696
Show file tree
Hide file tree
Showing 25 changed files with 2,232 additions and 1,396 deletions.
42 changes: 19 additions & 23 deletions content/renderer/gpu/renderer_gl_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "gpu/command_buffer/client/gles2_cmd_helper.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "gpu/command_buffer/client/gles2_lib.h"
#include "gpu/command_buffer/client/transfer_buffer.h"
#include "gpu/command_buffer/common/constants.h"
#endif // ENABLE_GPU

Expand All @@ -31,7 +32,9 @@ namespace {
const int32 kCommandBufferSize = 1024 * 1024;
// TODO(kbr): make the transfer buffer size configurable via context
// creation attributes.
const int32 kTransferBufferSize = 1024 * 1024;
const size_t kStartTransferBufferSize = 1 * 1024 * 1024;
const size_t kMinTransferBufferSize = 1 * 256 * 1024;
const size_t kMaxTransferBufferSize = 16 * 1024 * 1024;

// Singleton used to initialize and terminate the gles2 library.
class GLES2Initializer {
Expand Down Expand Up @@ -281,7 +284,7 @@ RendererGLContext::RendererGLContext(GpuChannelHost* channel)
parent_texture_id_(0),
command_buffer_(NULL),
gles2_helper_(NULL),
transfer_buffer_id_(-1),
transfer_buffer_(NULL),
gles2_implementation_(NULL),
last_error_(SUCCESS),
frame_number_(0) {
Expand Down Expand Up @@ -392,31 +395,24 @@ bool RendererGLContext::Initialize(bool onscreen,
TRACE_EVENT0("gpu", "RendererGLContext::Initialize::CreateTransferBuffer");
// Create a transfer buffer used to copy resources between the renderer
// process and the GPU process.
transfer_buffer_id_ = command_buffer_->CreateTransferBuffer(
kTransferBufferSize, gpu::kCommandBufferSharedMemoryId);
if (transfer_buffer_id_ < 0) {
Destroy();
return false;
}
}

// Map the buffer into the renderer process's address space.
gpu::Buffer transfer_buffer =
command_buffer_->GetTransferBuffer(transfer_buffer_id_);
if (!transfer_buffer.ptr) {
Destroy();
return false;
transfer_buffer_ = new gpu::TransferBuffer(gles2_helper_);
}

// Create the object exposing the OpenGL API.
gles2_implementation_ = new gpu::gles2::GLES2Implementation(
gles2_helper_,
transfer_buffer.size,
transfer_buffer.ptr,
transfer_buffer_id_,
transfer_buffer_,
share_resources,
bind_generates_resources);

if (!gles2_implementation_->Initialize(
kStartTransferBufferSize,
kMinTransferBufferSize,
kMaxTransferBufferSize)) {
Destroy();
return false;
}

return true;
}

Expand All @@ -437,10 +433,10 @@ void RendererGLContext::Destroy() {
gles2_implementation_ = NULL;
}

// Do not destroy this transfer buffer here, because commands are still
// in flight on the GPU process that may access them. When the command buffer
// is destroyed, the associated shared memory will be cleaned up.
transfer_buffer_id_ = -1;
if (transfer_buffer_) {
delete transfer_buffer_;
transfer_buffer_ = NULL;
}

delete gles2_helper_;
gles2_helper_ = NULL;
Expand Down
3 changes: 2 additions & 1 deletion content/renderer/gpu/renderer_gl_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class CommandBufferProxy;
class GURL;

namespace gpu {
class TransferBuffer;
namespace gles2 {
class GLES2CmdHelper;
class GLES2Implementation;
Expand Down Expand Up @@ -199,7 +200,7 @@ class RendererGLContext : public base::SupportsWeakPtr<RendererGLContext>,
uint32 parent_texture_id_;
CommandBufferProxy* command_buffer_;
gpu::gles2::GLES2CmdHelper* gles2_helper_;
int32 transfer_buffer_id_;
gpu::TransferBuffer* transfer_buffer_;
gpu::gles2::GLES2Implementation* gles2_implementation_;
Error last_error_;
int frame_number_;
Expand Down
15 changes: 9 additions & 6 deletions gpu/command_buffer/build_gles2_cmd_buffer.py
Original file line number Diff line number Diff line change
Expand Up @@ -3220,9 +3220,10 @@ def WriteGLES2ImplementationUnitTest(self, func, file):
typedef %(name)s::Result Result;
Result::Type result = 0;
Cmds expected;
expected.cmd.Init(%(cmd_args)s, transfer_buffer_id_, 0);
EXPECT_CALL(*command_buffer_, OnFlush(_))
.WillOnce(SetMemory(SizedResultHelper<Result::Type>(1)))
ExpectedMemoryInfo result1 = GetExpectedResultMemory(4);
expected.cmd.Init(%(cmd_args)s, result1.id, result1.offset);
EXPECT_CALL(*command_buffer(), OnFlush())
.WillOnce(SetMemory(result1.ptr, SizedResultHelper<Result::Type>(1)))
.RetiresOnSaturation();
gl_->%(name)s(%(args)s, &result);
EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
Expand Down Expand Up @@ -4145,10 +4146,12 @@ def WriteGLES2ImplementationUnitTest(self, func, file):
typedef %(name)s::Result Result;
Cmds expected;
expected.cmd.Init(1, transfer_buffer_id_, 0);
ExpectedMemoryInfo result1 =
GetExpectedResultMemory(sizeof(%(name)s::Result));
expected.cmd.Init(1, result1.id, result1.offset);
EXPECT_CALL(*command_buffer_, OnFlush(_))
.WillOnce(SetMemory(uint32(1)))
EXPECT_CALL(*command_buffer(), OnFlush())
.WillOnce(SetMemory(result1.ptr, uint32(1)))
.RetiresOnSaturation();
GLboolean result = gl_->%(name)s(1);
Expand Down
138 changes: 138 additions & 0 deletions gpu/command_buffer/client/client_test_helper.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Tests for GLES2Implementation.

#include "gpu/command_buffer/client/client_test_helper.h"

#include "gpu/command_buffer/common/command_buffer.h"
#include "gpu/command_buffer/client/cmd_buffer_helper.h"
#include "testing/gmock/include/gmock/gmock.h"

using ::testing::_;
using ::testing::Invoke;

namespace gpu {

MockCommandBufferBase::~MockCommandBufferBase() {
}

bool MockCommandBufferBase::Initialize() {
return true;
}

CommandBuffer::State MockCommandBufferBase::GetState() {
return state_;
}

CommandBuffer::State MockCommandBufferBase::GetLastState() {
return state_;
}

void MockCommandBufferBase::Flush(int32 put_offset) {
state_.put_offset = put_offset;
}

void MockCommandBufferBase::SetGetOffset(int32 get_offset) {
state_.get_offset = get_offset;
}

CommandBuffer::State MockCommandBufferBase::FlushSync(
int32 put_offset, int32 last_known_get) {
state_.put_offset = put_offset;
state_.get_offset = put_offset;
OnFlush();
return state_;
}

void MockCommandBufferBase::SetGetBuffer(int transfer_buffer_id) {
ring_buffer_buffer_ = GetTransferBuffer(transfer_buffer_id);
ring_buffer_ = static_cast<CommandBufferEntry*>(ring_buffer_buffer_.ptr);
state_.num_entries = ring_buffer_buffer_.size / sizeof(ring_buffer_[0]);
state_.token = 10000; // All token checks in the tests should pass.
}

// Get's the Id of the next transfer buffer that will be returned
// by CreateTransferBuffer. This is useful for testing expected ids.
int32 MockCommandBufferBase::GetNextFreeTransferBufferId() {
for (size_t ii = 0; ii < arraysize(transfer_buffers_); ++ii) {
if (!transfer_buffers_[ii].get()) {
return kTransferBufferBaseId + ii;
}
}
return -1;
}

int32 MockCommandBufferBase::CreateTransferBuffer(
size_t size, int32 id_request) {
int32 id = GetNextFreeTransferBufferId();
if (id >= 0) {
int32 ndx = id - kTransferBufferBaseId;
transfer_buffers_[ndx].reset(new int8[size]);
transfer_buffer_buffers_[ndx].ptr = transfer_buffers_[ndx].get();
transfer_buffer_buffers_[ndx].size = size;
}
return id;
}

void MockCommandBufferBase::DestroyTransferBufferHelper(int32 id) {
GPU_DCHECK_GE(id, kTransferBufferBaseId);
GPU_DCHECK_LT(id, kTransferBufferBaseId + kMaxTransferBuffers);
id -= kTransferBufferBaseId;
transfer_buffers_[id].reset();
transfer_buffer_buffers_[id] = Buffer();
}

Buffer MockCommandBufferBase::GetTransferBuffer(int32 id) {
GPU_DCHECK_GE(id, kTransferBufferBaseId);
GPU_DCHECK_LT(id, kTransferBufferBaseId + kMaxTransferBuffers);
return transfer_buffer_buffers_[id - kTransferBufferBaseId];
}

int32 MockCommandBufferBase::RegisterTransferBuffer(
base::SharedMemory* shared_memory,
size_t size,
int32 id_request) {
GPU_NOTREACHED();
return -1;
}

void MockCommandBufferBase::SetToken(int32 token) {
GPU_NOTREACHED();
state_.token = token;
}

void MockCommandBufferBase::SetParseError(error::Error error) {
GPU_NOTREACHED();
state_.error = error;
}

void MockCommandBufferBase::SetContextLostReason(
error::ContextLostReason reason) {
GPU_NOTREACHED();
state_.context_lost_reason = reason;
}

// GCC requires these declarations, but MSVC requires they not be present
#ifndef _MSC_VER
const int32 MockCommandBufferBase::kTransferBufferBaseId;
const int32 MockCommandBufferBase::kMaxTransferBuffers;
#endif

MockClientCommandBuffer::MockClientCommandBuffer() {
DelegateToFake();
}

MockClientCommandBuffer::~MockClientCommandBuffer() {
}

void MockClientCommandBuffer::DelegateToFake() {
ON_CALL(*this, DestroyTransferBuffer(_))
.WillByDefault(Invoke(
this, &MockCommandBufferBase::DestroyTransferBufferHelper));
}

} // namespace gpu


76 changes: 76 additions & 0 deletions gpu/command_buffer/client/client_test_helper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Helper classes for implementing gpu client side unit tests.

#ifndef GPU_COMMAND_BUFFER_CLIENT_CLIENT_TEST_HELPER_H_
#define GPU_COMMAND_BUFFER_CLIENT_CLIENT_TEST_HELPER_H_

#include "gpu/command_buffer/common/cmd_buffer_common.h"
#include "gpu/command_buffer/common/command_buffer.h"
#include "gpu/command_buffer/common/compiler_specific.h"
#include "gpu/command_buffer/common/scoped_ptr.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace gpu {

class CommandBufferHelper;

class MockCommandBufferBase : public CommandBuffer {
public:
static const int32 kTransferBufferBaseId = 0x123;
static const int32 kMaxTransferBuffers = 6;

MockCommandBufferBase() { }
virtual ~MockCommandBufferBase();

virtual bool Initialize() OVERRIDE;
virtual State GetState() OVERRIDE;
virtual State GetLastState() OVERRIDE;
virtual void Flush(int32 put_offset) OVERRIDE;
virtual State FlushSync(int32 put_offset, int32 last_known_get) OVERRIDE;
virtual void SetGetBuffer(int transfer_buffer_id) OVERRIDE;
virtual void SetGetOffset(int32 get_offset) OVERRIDE;
virtual int32 CreateTransferBuffer(size_t size, int32 id_request) OVERRIDE;
virtual Buffer GetTransferBuffer(int32 id) OVERRIDE;
virtual int32 RegisterTransferBuffer(base::SharedMemory* shared_memory,
size_t size,
int32 id_request) OVERRIDE;
virtual void SetToken(int32 token) OVERRIDE;
virtual void SetParseError(error::Error error) OVERRIDE;
virtual void SetContextLostReason(error::ContextLostReason reason) OVERRIDE;

// Get's the Id of the next transfer buffer that will be returned
// by CreateTransferBuffer. This is useful for testing expected ids.
int32 GetNextFreeTransferBufferId();

void DestroyTransferBufferHelper(int32 id);

virtual void OnFlush() = 0;

private:
scoped_array<int8> transfer_buffers_[kMaxTransferBuffers];
Buffer transfer_buffer_buffers_[kMaxTransferBuffers];
CommandBufferEntry* ring_buffer_;
Buffer ring_buffer_buffer_;
State state_;
};

class MockClientCommandBuffer : public MockCommandBufferBase {
public:
MockClientCommandBuffer();
virtual ~MockClientCommandBuffer();

// This is so we can use all the gmock functions when Flush is called.
MOCK_METHOD0(OnFlush, void());
MOCK_METHOD1(DestroyTransferBuffer, void(int32 id));

void DelegateToFake();
};

} // namespace gpu

#endif // GPU_COMMAND_BUFFER_CLIENT_CLIENT_TEST_HELPER_H_

Loading

0 comments on commit d5c7696

Please sign in to comment.