Skip to content

Commit

Permalink
Add support for multithreading the GPU command buffer.
Browse files Browse the repository at this point in the history
The CommandBufferProxyImpl has a lock which is held on receiving messages from the GPU and must be held by any code that executes GPU commands if it can be used from multiple threads.

Review URL: https://codereview.chromium.org/879403004

Cr-Commit-Position: refs/heads/master@{#315889}
  • Loading branch information
jbauman2 authored and Commit bot committed Feb 12, 2015
1 parent 1084249 commit 6875d4e
Show file tree
Hide file tree
Showing 12 changed files with 76 additions and 1 deletion.
38 changes: 37 additions & 1 deletion content/common/gpu/client/command_buffer_proxy_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ namespace content {

CommandBufferProxyImpl::CommandBufferProxyImpl(GpuChannelHost* channel,
int route_id)
: channel_(channel),
: lock_(nullptr),
channel_(channel),
route_id_(route_id),
flush_count_(0),
last_put_offset_(-1),
Expand All @@ -42,6 +43,9 @@ CommandBufferProxyImpl::~CommandBufferProxyImpl() {
}

bool CommandBufferProxyImpl::OnMessageReceived(const IPC::Message& message) {
scoped_ptr<base::AutoLock> lock;
if (lock_)
lock.reset(new base::AutoLock(*lock_));
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(CommandBufferProxyImpl, message)
IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_Destroyed, OnDestroyed);
Expand All @@ -60,10 +64,14 @@ bool CommandBufferProxyImpl::OnMessageReceived(const IPC::Message& message) {
}

void CommandBufferProxyImpl::OnChannelError() {
scoped_ptr<base::AutoLock> lock;
if (lock_)
lock.reset(new base::AutoLock(*lock_));
OnDestroyed(gpu::error::kUnknown);
}

void CommandBufferProxyImpl::OnDestroyed(gpu::error::ContextLostReason reason) {
CheckLock();
// Prevent any further messages from being sent.
channel_ = NULL;

Expand All @@ -88,6 +96,7 @@ void CommandBufferProxyImpl::OnConsoleMessage(

void CommandBufferProxyImpl::SetMemoryAllocationChangedCallback(
const MemoryAllocationChangedCallback& callback) {
CheckLock();
if (last_state_.error != gpu::error::kNoError)
return;

Expand All @@ -97,11 +106,13 @@ void CommandBufferProxyImpl::SetMemoryAllocationChangedCallback(
}

void CommandBufferProxyImpl::AddDeletionObserver(DeletionObserver* observer) {
CheckLock();
deletion_observers_.AddObserver(observer);
}

void CommandBufferProxyImpl::RemoveDeletionObserver(
DeletionObserver* observer) {
CheckLock();
deletion_observers_.RemoveObserver(observer);
}

Expand All @@ -121,6 +132,7 @@ void CommandBufferProxyImpl::OnSignalSyncPointAck(uint32 id) {

void CommandBufferProxyImpl::SetChannelErrorCallback(
const base::Closure& callback) {
CheckLock();
channel_error_callback_ = callback;
}

Expand Down Expand Up @@ -171,6 +183,7 @@ int32 CommandBufferProxyImpl::GetLastToken() {
}

void CommandBufferProxyImpl::Flush(int32 put_offset) {
CheckLock();
if (last_state_.error != gpu::error::kNoError)
return;

Expand Down Expand Up @@ -213,16 +226,19 @@ void CommandBufferProxyImpl::OrderingBarrier(int32 put_offset) {

void CommandBufferProxyImpl::SetLatencyInfo(
const std::vector<ui::LatencyInfo>& latency_info) {
CheckLock();
for (size_t i = 0; i < latency_info.size(); i++)
latency_info_.push_back(latency_info[i]);
}

void CommandBufferProxyImpl::SetSwapBuffersCompletionCallback(
const SwapBuffersCompletionCallback& callback) {
CheckLock();
swap_buffers_completion_callback_ = callback;
}

void CommandBufferProxyImpl::WaitForTokenInRange(int32 start, int32 end) {
CheckLock();
TRACE_EVENT2("gpu",
"CommandBufferProxyImpl::WaitForToken",
"start",
Expand All @@ -242,6 +258,7 @@ void CommandBufferProxyImpl::WaitForTokenInRange(int32 start, int32 end) {
}

void CommandBufferProxyImpl::WaitForGetOffsetInRange(int32 start, int32 end) {
CheckLock();
TRACE_EVENT2("gpu",
"CommandBufferProxyImpl::WaitForGetOffset",
"start",
Expand All @@ -261,6 +278,7 @@ void CommandBufferProxyImpl::WaitForGetOffsetInRange(int32 start, int32 end) {
}

void CommandBufferProxyImpl::SetGetBuffer(int32 shm_id) {
CheckLock();
if (last_state_.error != gpu::error::kNoError)
return;

Expand All @@ -271,6 +289,7 @@ void CommandBufferProxyImpl::SetGetBuffer(int32 shm_id) {
scoped_refptr<gpu::Buffer> CommandBufferProxyImpl::CreateTransferBuffer(
size_t size,
int32* id) {
CheckLock();
*id = -1;

if (last_state_.error != gpu::error::kNoError)
Expand Down Expand Up @@ -309,6 +328,7 @@ scoped_refptr<gpu::Buffer> CommandBufferProxyImpl::CreateTransferBuffer(
}

void CommandBufferProxyImpl::DestroyTransferBuffer(int32 id) {
CheckLock();
if (last_state_.error != gpu::error::kNoError)
return;

Expand All @@ -323,6 +343,7 @@ int32_t CommandBufferProxyImpl::CreateImage(ClientBuffer buffer,
size_t width,
size_t height,
unsigned internalformat) {
CheckLock();
if (last_state_.error != gpu::error::kNoError)
return -1;

Expand Down Expand Up @@ -362,6 +383,7 @@ int32_t CommandBufferProxyImpl::CreateImage(ClientBuffer buffer,
}

void CommandBufferProxyImpl::DestroyImage(int32 id) {
CheckLock();
if (last_state_.error != gpu::error::kNoError)
return;

Expand All @@ -373,6 +395,7 @@ int32_t CommandBufferProxyImpl::CreateGpuMemoryBufferImage(
size_t height,
unsigned internalformat,
unsigned usage) {
CheckLock();
scoped_ptr<gfx::GpuMemoryBuffer> buffer(
channel_->gpu_memory_buffer_manager()->AllocateGpuMemoryBuffer(
gfx::Size(width, height),
Expand All @@ -389,6 +412,7 @@ int CommandBufferProxyImpl::GetRouteID() const {
}

uint32 CommandBufferProxyImpl::CreateStreamTexture(uint32 texture_id) {
CheckLock();
if (last_state_.error != gpu::error::kNoError)
return 0;

Expand All @@ -403,7 +427,12 @@ uint32 CommandBufferProxyImpl::CreateStreamTexture(uint32 texture_id) {
return stream_id;
}

void CommandBufferProxyImpl::SetLock(base::Lock* lock) {
lock_ = lock;
}

uint32 CommandBufferProxyImpl::InsertSyncPoint() {
CheckLock();
if (last_state_.error != gpu::error::kNoError)
return 0;

Expand All @@ -413,6 +442,7 @@ uint32 CommandBufferProxyImpl::InsertSyncPoint() {
}

uint32_t CommandBufferProxyImpl::InsertFutureSyncPoint() {
CheckLock();
if (last_state_.error != gpu::error::kNoError)
return 0;

Expand All @@ -422,6 +452,7 @@ uint32_t CommandBufferProxyImpl::InsertFutureSyncPoint() {
}

void CommandBufferProxyImpl::RetireSyncPoint(uint32_t sync_point) {
CheckLock();
if (last_state_.error != gpu::error::kNoError)
return;

Expand All @@ -430,6 +461,7 @@ void CommandBufferProxyImpl::RetireSyncPoint(uint32_t sync_point) {

void CommandBufferProxyImpl::SignalSyncPoint(uint32 sync_point,
const base::Closure& callback) {
CheckLock();
if (last_state_.error != gpu::error::kNoError)
return;

Expand All @@ -445,6 +477,7 @@ void CommandBufferProxyImpl::SignalSyncPoint(uint32 sync_point,

void CommandBufferProxyImpl::SignalQuery(uint32 query,
const base::Closure& callback) {
CheckLock();
if (last_state_.error != gpu::error::kNoError)
return;

Expand All @@ -467,13 +500,15 @@ void CommandBufferProxyImpl::SignalQuery(uint32 query,
}

void CommandBufferProxyImpl::SetSurfaceVisible(bool visible) {
CheckLock();
if (last_state_.error != gpu::error::kNoError)
return;

Send(new GpuCommandBufferMsg_SetSurfaceVisible(route_id_, visible));
}

bool CommandBufferProxyImpl::ProduceFrontBuffer(const gpu::Mailbox& mailbox) {
CheckLock();
if (last_state_.error != gpu::error::kNoError)
return false;

Expand Down Expand Up @@ -533,6 +568,7 @@ void CommandBufferProxyImpl::OnUpdateState(

void CommandBufferProxyImpl::SetOnConsoleMessageCallback(
const GpuConsoleMessageCallback& callback) {
CheckLock();
console_message_callback_ = callback;
}

Expand Down
8 changes: 8 additions & 0 deletions content/common/gpu/client/command_buffer_proxy_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ class CommandBufferProxyImpl
void SignalQuery(uint32 query, const base::Closure& callback) override;
void SetSurfaceVisible(bool visible) override;
uint32 CreateStreamTexture(uint32 texture_id) override;
void SetLock(base::Lock* lock) override;

int GetRouteID() const;
bool ProduceFrontBuffer(const gpu::Mailbox& mailbox);
Expand Down Expand Up @@ -157,6 +158,11 @@ class CommandBufferProxyImpl
typedef base::ScopedPtrHashMap<int32, gfx::GpuMemoryBuffer>
GpuMemoryBufferMap;

void CheckLock() {
if (lock_)
lock_->AssertAcquired();
}

// Send an IPC message over the GPU channel. This is private to fully
// encapsulate the channel; all callers of this function must explicitly
// verify that the context has not been lost.
Expand All @@ -176,6 +182,8 @@ class CommandBufferProxyImpl
// The shared memory area used to update state.
gpu::CommandBufferSharedState* shared_state() const;

base::Lock* lock_;

// Unowned list of DeletionObservers.
ObserverList<DeletionObserver> deletion_observers_;

Expand Down
1 change: 1 addition & 0 deletions gpu/command_buffer/client/client_test_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ class MockClientGpuControl : public GpuControl {
MOCK_METHOD2(SignalQuery, void(uint32 query, const base::Closure& callback));
MOCK_METHOD1(SetSurfaceVisible, void(bool visible));
MOCK_METHOD1(CreateStreamTexture, uint32(uint32));
MOCK_METHOD1(SetLock, void(base::Lock*));

private:
DISALLOW_COPY_AND_ASSIGN(MockClientGpuControl);
Expand Down
10 changes: 10 additions & 0 deletions gpu/command_buffer/client/gpu_control.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@

extern "C" typedef struct _ClientBuffer* ClientBuffer;

namespace base {
class Lock;
}

namespace gfx {
class GpuMemoryBuffer;
}
Expand Down Expand Up @@ -75,6 +79,12 @@ class GPU_EXPORT GpuControl {
// returns a stream identifier.
virtual uint32_t CreateStreamTexture(uint32_t texture_id) = 0;

// Sets a lock this will be held on every callback from the GPU
// implementation. This lock must be set and must be held on every call into
// the GPU implementation if it is to be used from multiple threads. This
// may not be supported with all implementations.
virtual void SetLock(base::Lock*) = 0;

private:
DISALLOW_COPY_AND_ASSIGN(GpuControl);
};
Expand Down
4 changes: 4 additions & 0 deletions gpu/command_buffer/service/in_process_command_buffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,10 @@ uint32 InProcessCommandBuffer::CreateStreamTexture(uint32 texture_id) {
return stream_id;
}

void InProcessCommandBuffer::SetLock(base::Lock*) {
NOTIMPLEMENTED();
}

uint32 InProcessCommandBuffer::CreateStreamTextureOnGpuThread(
uint32 client_texture_id) {
#if defined(OS_ANDROID)
Expand Down
1 change: 1 addition & 0 deletions gpu/command_buffer/service/in_process_command_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer,
void SignalQuery(uint32 query_id, const base::Closure& callback) override;
void SetSurfaceVisible(bool visible) override;
uint32 CreateStreamTexture(uint32 texture_id) override;
void SetLock(base::Lock*) override;

// The serializer interface to the GPU service (i.e. thread).
class Service {
Expand Down
4 changes: 4 additions & 0 deletions gpu/command_buffer/tests/gl_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -429,4 +429,8 @@ uint32 GLManager::CreateStreamTexture(uint32 texture_id) {
return 0;
}

void GLManager::SetLock(base::Lock*) {
NOTIMPLEMENTED();
}

} // namespace gpu
1 change: 1 addition & 0 deletions gpu/command_buffer/tests/gl_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ class GLManager : private GpuControl {
void SignalQuery(uint32 query, const base::Closure& callback) override;
void SetSurfaceVisible(bool visible) override;
uint32 CreateStreamTexture(uint32 texture_id) override;
void SetLock(base::Lock*) override;

private:
void PumpCommands();
Expand Down
4 changes: 4 additions & 0 deletions gpu/gles2_conform_support/egl/display.cc
Original file line number Diff line number Diff line change
Expand Up @@ -335,4 +335,8 @@ uint32 Display::CreateStreamTexture(uint32 texture_id) {
return 0;
}

void Display::SetLock(base::Lock*) {
NOTIMPLEMENTED();
}

} // namespace egl
1 change: 1 addition & 0 deletions gpu/gles2_conform_support/egl/display.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ class Display : private gpu::GpuControl {
void SignalQuery(uint32 query, const base::Closure& callback) override;
void SetSurfaceVisible(bool visible) override;
uint32 CreateStreamTexture(uint32 texture_id) override;
void SetLock(base::Lock*) override;

private:
EGLNativeDisplayType display_id_;
Expand Down
4 changes: 4 additions & 0 deletions ppapi/proxy/ppapi_command_buffer_proxy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,10 @@ uint32 PpapiCommandBufferProxy::CreateStreamTexture(uint32 texture_id) {
return 0;
}

void PpapiCommandBufferProxy::SetLock(base::Lock*) {
NOTIMPLEMENTED();
}

uint32 PpapiCommandBufferProxy::InsertSyncPoint() {
uint32 sync_point = 0;
if (last_state_.error == gpu::error::kNoError) {
Expand Down
1 change: 1 addition & 0 deletions ppapi/proxy/ppapi_command_buffer_proxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class PPAPI_PROXY_EXPORT PpapiCommandBufferProxy : public gpu::CommandBuffer,
const base::Closure& callback) override;
virtual void SetSurfaceVisible(bool visible) override;
virtual uint32 CreateStreamTexture(uint32 texture_id) override;
void SetLock(base::Lock*) override;

private:
bool Send(IPC::Message* msg);
Expand Down

0 comments on commit 6875d4e

Please sign in to comment.