summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorkbr@google.com <kbr@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-26 20:16:18 +0000
committerkbr@google.com <kbr@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-26 20:16:18 +0000
commit33da8041706bbe87ec9ff8d95854bf7075ab2d7a (patch)
tree518fd9b01ac6355816acd64bfb7f9ce037274598 /gpu
parent76d20290e1a84f5a18c63c0f905062b986f01f55 (diff)
downloadchromium_src-33da8041706bbe87ec9ff8d95854bf7075ab2d7a.zip
chromium_src-33da8041706bbe87ec9ff8d95854bf7075ab2d7a.tar.gz
chromium_src-33da8041706bbe87ec9ff8d95854bf7075ab2d7a.tar.bz2
Add flow control between renderer and GPU processes, and, on Mac OS X,
between GPU process and browser process. Thanks to Al Patrick for the renderer<->GPU flow control mechanism. This CL prevents the renderer from issuing more OpenGL work than the GPU process can execute, and, on the Mac, prevents the combination of the renderer and GPU processes from transmitting more frames via IOSurfaces from the GPU to the browser process than can be handled by the GPU. This fix causes the renderer to block inside ggl::SwapBuffers() when it gets too far ahead. Different strategies can be considered going forward, including measuring frame rates in the GPU and renderer processes and trying to match them via techniques such as delaying the execution of some timers. However, despite the general undesirability of blocking the render thread, this fix results in a significant performance improvement. With this fix integrated, a fill-limited test case from Chris Rogers displays at 60 FPS instead of 15 FPS on a Mac Pro. Gregg Tavares' aquarium from webglsamples.googlecode.com displays at 30 FPS instead of 4 or 5 FPS on a MacBook Pro. The frame rates measured at the JavaScript level now match the actual frame rate of the browser, where previously they were much higher since they were issuing more work than the browser could render. A few other minor OpenGL bugs potentially impacting the correctness of the Mac compositor are being fixed as well in this CL. Verified that WebGL, CSS 3D and YouTube (Core Animation plugin) content all work. BUG=63539 TEST=none Review URL: http://codereview.chromium.org/5317007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@67470 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rw-r--r--gpu/command_buffer/service/gpu_processor.cc37
-rw-r--r--gpu/command_buffer/service/gpu_processor.h14
-rw-r--r--gpu/command_buffer/service/gpu_processor_mac.cc11
3 files changed, 59 insertions, 3 deletions
diff --git a/gpu/command_buffer/service/gpu_processor.cc b/gpu/command_buffer/service/gpu_processor.cc
index 275f3cb..57d9052 100644
--- a/gpu/command_buffer/service/gpu_processor.cc
+++ b/gpu/command_buffer/service/gpu_processor.cc
@@ -16,6 +16,10 @@ GPUProcessor::GPUProcessor(CommandBuffer* command_buffer,
gles2::ContextGroup* group)
: command_buffer_(command_buffer),
commands_per_update_(100),
+#if defined(OS_MACOSX)
+ swap_buffers_count_(0),
+ acknowledged_swap_buffers_count_(0),
+#endif
method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
DCHECK(command_buffer);
decoder_.reset(gles2::GLES2Decoder::Create(group));
@@ -28,6 +32,10 @@ GPUProcessor::GPUProcessor(CommandBuffer* command_buffer,
int commands_per_update)
: command_buffer_(command_buffer),
commands_per_update_(commands_per_update),
+#if defined(OS_MACOSX)
+ swap_buffers_count_(0),
+ acknowledged_swap_buffers_count_(0),
+#endif
method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
DCHECK(command_buffer);
decoder_.reset(decoder);
@@ -87,6 +95,12 @@ void GPUProcessor::DestroyCommon() {
parser_.reset();
}
+#if defined(OS_MACOSX)
+namespace {
+const unsigned int kMaxOutstandingSwapBuffersCallsPerOnscreenContext = 1;
+}
+#endif
+
void GPUProcessor::ProcessCommands() {
CommandBuffer::State state = command_buffer_->GetState();
if (state.error != error::kNoError)
@@ -102,6 +116,19 @@ void GPUProcessor::ProcessCommands() {
parser_->set_put(state.put_offset);
+#if defined(OS_MACOSX)
+ bool do_rate_limiting = surface_.get() != NULL;
+ // Don't swamp the browser process with SwapBuffers calls it can't handle.
+ if (do_rate_limiting &&
+ swap_buffers_count_ - acknowledged_swap_buffers_count_ >=
+ kMaxOutstandingSwapBuffersCallsPerOnscreenContext) {
+ // Stop doing work on this command buffer. In the GPU process,
+ // receipt of the GpuMsg_AcceleratedSurfaceBuffersSwappedACK
+ // message causes ProcessCommands to be scheduled again.
+ return;
+ }
+#endif
+
int commands_processed = 0;
while (commands_processed < commands_per_update_ && !parser_->IsEmpty()) {
error::Error error = parser_->ProcessCommand();
@@ -115,12 +142,16 @@ void GPUProcessor::ProcessCommands() {
command_buffer_->SetGetOffset(static_cast<int32>(parser_->get()));
if (!parser_->IsEmpty()) {
- MessageLoop::current()->PostTask(
- FROM_HERE,
- method_factory_.NewRunnableMethod(&GPUProcessor::ProcessCommands));
+ ScheduleProcessCommands();
}
}
+void GPUProcessor::ScheduleProcessCommands() {
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ method_factory_.NewRunnableMethod(&GPUProcessor::ProcessCommands));
+}
+
Buffer GPUProcessor::GetSharedMemoryBuffer(int32 shm_id) {
return command_buffer_->GetTransferBuffer(shm_id);
}
diff --git a/gpu/command_buffer/service/gpu_processor.h b/gpu/command_buffer/service/gpu_processor.h
index 247c4c5..9d30f980 100644
--- a/gpu/command_buffer/service/gpu_processor.h
+++ b/gpu/command_buffer/service/gpu_processor.h
@@ -61,6 +61,9 @@ class GPUProcessor : public CommandBufferEngine {
virtual void ProcessCommands();
+ // Helper which causes a call to ProcessCommands to be scheduled later.
+ void ScheduleProcessCommands();
+
// Implementation of CommandBufferEngine.
virtual Buffer GetSharedMemoryBuffer(int32 shm_id);
virtual void set_token(int32 token);
@@ -85,6 +88,15 @@ class GPUProcessor : public CommandBufferEngine {
Callback1<TransportDIB::Id>::Type* deallocator);
// Returns the id of the current IOSurface, or 0.
virtual uint64 GetSurfaceId();
+ // To prevent the GPU process from overloading the browser process,
+ // we need to track the number of swap buffers calls issued and
+ // acknowledged per on-screen (IOSurface-backed) context, and keep
+ // the GPU from getting too far ahead of the browser. Note that this
+ // is also predicated on a flow control mechanism between the
+ // renderer and GPU processes.
+ uint64 swap_buffers_count() const;
+ void set_acknowledged_swap_buffers_count(
+ uint64 acknowledged_swap_buffers_count);
#endif
// Sets a callback that is called when a glResizeCHROMIUM command
@@ -126,6 +138,8 @@ class GPUProcessor : public CommandBufferEngine {
#if defined(OS_MACOSX)
scoped_ptr<AcceleratedSurface> surface_;
+ uint64 swap_buffers_count_;
+ uint64 acknowledged_swap_buffers_count_;
#endif
ScopedRunnableMethodFactory<GPUProcessor> method_factory_;
diff --git a/gpu/command_buffer/service/gpu_processor_mac.cc b/gpu/command_buffer/service/gpu_processor_mac.cc
index 99721e9..63a894d 100644
--- a/gpu/command_buffer/service/gpu_processor_mac.cc
+++ b/gpu/command_buffer/service/gpu_processor_mac.cc
@@ -99,11 +99,22 @@ uint64 GPUProcessor::GetSurfaceId() {
return surface_->GetSurfaceId();
}
+uint64 GPUProcessor::swap_buffers_count() const {
+ return swap_buffers_count_;
+}
+
+void GPUProcessor::set_acknowledged_swap_buffers_count(
+ uint64 acknowledged_swap_buffers_count) {
+ acknowledged_swap_buffers_count_ = acknowledged_swap_buffers_count;
+}
+
void GPUProcessor::WillSwapBuffers() {
DCHECK(decoder_.get());
DCHECK(decoder_->GetGLContext());
DCHECK(decoder_->GetGLContext()->IsCurrent());
+ ++swap_buffers_count_;
+
if (surface_.get()) {
surface_->SwapBuffers();
}