Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(153)

Side by Side Diff: content/common/gpu/gpu_command_buffer_stub.cc

Issue 12040049: gpu: Implement idle async pixel transfers. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase and prevent starvation Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/bind.h" 5 #include "base/bind.h"
6 #include "base/bind_helpers.h" 6 #include "base/bind_helpers.h"
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/debug/trace_event.h" 8 #include "base/debug/trace_event.h"
9 #include "base/hash.h" 9 #include "base/hash.h"
10 #include "base/shared_memory.h" 10 #include "base/shared_memory.h"
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 static size_t g_last_url_hash = 0; 81 static size_t g_last_url_hash = 0;
82 if (url_hash != g_last_url_hash) { 82 if (url_hash != g_last_url_hash) {
83 g_last_url_hash = url_hash; 83 g_last_url_hash = url_hash;
84 GetContentClient()->SetActiveURL(url); 84 GetContentClient()->SetActiveURL(url);
85 } 85 }
86 } 86 }
87 87
88 // The first time polling a fence, delay some extra time to allow other 88 // The first time polling a fence, delay some extra time to allow other
89 // stubs to process some work, or else the timing of the fences could 89 // stubs to process some work, or else the timing of the fences could
90 // allow a pattern of alternating fast and slow frames to occur. 90 // allow a pattern of alternating fast and slow frames to occur.
91 const int64 kHandleMoreWorkPeriodMs = 2; 91 const int64 kHandleMoreWorkPeriodMicroseconds = 2000;
92 const int64 kHandleMoreWorkPeriodBusyMs = 1; 92 const int64 kHandleMoreWorkPeriodBusyMicroseconds = 1000;
93
94 // Use a shorter delay when there'ss idle work to be done.
Sami 2013/03/07 16:57:19 Typo: there'ss
reveman 2013/03/07 20:21:04 Done.
95 const int64 kHandleMoreIdleWorkPeriodBusyMicroseconds = 100;
96 // Prevents idle work from being starved.
97 const int64 kMaxTimeSinceIdleMicroseconds = 10000;
93 98
94 } // namespace 99 } // namespace
95 100
96 GpuCommandBufferStub::GpuCommandBufferStub( 101 GpuCommandBufferStub::GpuCommandBufferStub(
97 GpuChannel* channel, 102 GpuChannel* channel,
98 GpuCommandBufferStub* share_group, 103 GpuCommandBufferStub* share_group,
99 const gfx::GLSurfaceHandle& handle, 104 const gfx::GLSurfaceHandle& handle,
100 gpu::gles2::MailboxManager* mailbox_manager, 105 gpu::gles2::MailboxManager* mailbox_manager,
101 gpu::gles2::ImageManager* image_manager, 106 gpu::gles2::ImageManager* image_manager,
102 const gfx::Size& size, 107 const gfx::Size& size,
(...skipping 16 matching lines...) Expand all
119 route_id_(route_id), 124 route_id_(route_id),
120 surface_id_(surface_id), 125 surface_id_(surface_id),
121 software_(software), 126 software_(software),
122 last_flush_count_(0), 127 last_flush_count_(0),
123 last_memory_allocation_valid_(false), 128 last_memory_allocation_valid_(false),
124 parent_stub_for_initialization_(), 129 parent_stub_for_initialization_(),
125 parent_texture_for_initialization_(0), 130 parent_texture_for_initialization_(0),
126 watchdog_(watchdog), 131 watchdog_(watchdog),
127 sync_point_wait_count_(0), 132 sync_point_wait_count_(0),
128 delayed_work_scheduled_(false), 133 delayed_work_scheduled_(false),
134 is_idle_(false),
129 active_url_(active_url), 135 active_url_(active_url),
130 total_gpu_memory_(0) { 136 total_gpu_memory_(0) {
131 active_url_hash_ = base::Hash(active_url.possibly_invalid_spec()); 137 active_url_hash_ = base::Hash(active_url.possibly_invalid_spec());
132 FastSetActiveURL(active_url_, active_url_hash_); 138 FastSetActiveURL(active_url_, active_url_hash_);
133 if (share_group) { 139 if (share_group) {
134 context_group_ = share_group->context_group_; 140 context_group_ = share_group->context_group_;
135 } else { 141 } else {
136 context_group_ = new gpu::gles2::ContextGroup( 142 context_group_ = new gpu::gles2::ContextGroup(
137 mailbox_manager, 143 mailbox_manager,
138 image_manager, 144 image_manager,
(...skipping 20 matching lines...) Expand all
159 // messages directed at the command buffer. This ensures that the message 165 // messages directed at the command buffer. This ensures that the message
160 // handler can assume that the context is current (not necessary for 166 // handler can assume that the context is current (not necessary for
161 // Echo, RetireSyncPoint, or WaitSyncPoint). 167 // Echo, RetireSyncPoint, or WaitSyncPoint).
162 if (decoder_.get() && 168 if (decoder_.get() &&
163 message.type() != GpuCommandBufferMsg_Echo::ID && 169 message.type() != GpuCommandBufferMsg_Echo::ID &&
164 message.type() != GpuCommandBufferMsg_RetireSyncPoint::ID) { 170 message.type() != GpuCommandBufferMsg_RetireSyncPoint::ID) {
165 if (!MakeCurrent()) 171 if (!MakeCurrent())
166 return false; 172 return false;
167 } 173 }
168 174
175 is_idle_ = false;
176
169 // Always use IPC_MESSAGE_HANDLER_DELAY_REPLY for synchronous message handlers 177 // Always use IPC_MESSAGE_HANDLER_DELAY_REPLY for synchronous message handlers
170 // here. This is so the reply can be delayed if the scheduler is unscheduled. 178 // here. This is so the reply can be delayed if the scheduler is unscheduled.
171 bool handled = true; 179 bool handled = true;
172 IPC_BEGIN_MESSAGE_MAP(GpuCommandBufferStub, message) 180 IPC_BEGIN_MESSAGE_MAP(GpuCommandBufferStub, message)
173 IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_Initialize, 181 IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_Initialize,
174 OnInitialize); 182 OnInitialize);
175 IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_SetGetBuffer, 183 IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_SetGetBuffer,
176 OnSetGetBuffer); 184 OnSetGetBuffer);
177 IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_SetParent, 185 IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_SetParent,
178 OnSetParent); 186 OnSetParent);
(...skipping 25 matching lines...) Expand all
204 OnSignalSyncPoint) 212 OnSignalSyncPoint)
205 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SendClientManagedMemoryStats, 213 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SendClientManagedMemoryStats,
206 OnReceivedClientManagedMemoryStats) 214 OnReceivedClientManagedMemoryStats)
207 IPC_MESSAGE_HANDLER( 215 IPC_MESSAGE_HANDLER(
208 GpuCommandBufferMsg_SetClientHasMemoryAllocationChangedCallback, 216 GpuCommandBufferMsg_SetClientHasMemoryAllocationChangedCallback,
209 OnSetClientHasMemoryAllocationChangedCallback) 217 OnSetClientHasMemoryAllocationChangedCallback)
210 IPC_MESSAGE_UNHANDLED(handled = false) 218 IPC_MESSAGE_UNHANDLED(handled = false)
211 IPC_END_MESSAGE_MAP() 219 IPC_END_MESSAGE_MAP()
212 220
213 // Ensure that any delayed work that was created will be handled. 221 // Ensure that any delayed work that was created will be handled.
214 ScheduleDelayedWork(kHandleMoreWorkPeriodMs); 222 ScheduleDelayedWork(kHandleMoreWorkPeriodMicroseconds);
215 223
216 DCHECK(handled); 224 DCHECK(handled);
217 return handled; 225 return handled;
218 } 226 }
219 227
220 bool GpuCommandBufferStub::Send(IPC::Message* message) { 228 bool GpuCommandBufferStub::Send(IPC::Message* message) {
221 return channel_->Send(message); 229 return channel_->Send(message);
222 } 230 }
223 231
224 bool GpuCommandBufferStub::IsScheduled() { 232 bool GpuCommandBufferStub::IsScheduled() {
225 return (!scheduler_.get() || scheduler_->IsScheduled()); 233 return (!scheduler_.get() || scheduler_->IsScheduled());
226 } 234 }
227 235
228 bool GpuCommandBufferStub::HasMoreWork() { 236 bool GpuCommandBufferStub::HasMoreWork() {
229 return scheduler_.get() && scheduler_->HasMoreWork(); 237 return scheduler_.get() && scheduler_->HasMoreWork();
230 } 238 }
231 239
232 void GpuCommandBufferStub::PollWork() { 240 void GpuCommandBufferStub::PollWork() {
233 TRACE_EVENT0("gpu", "GpuCommandBufferStub::PollWork"); 241 TRACE_EVENT0("gpu", "GpuCommandBufferStub::PollWork");
234 delayed_work_scheduled_ = false; 242 delayed_work_scheduled_ = false;
235 FastSetActiveURL(active_url_, active_url_hash_); 243 FastSetActiveURL(active_url_, active_url_hash_);
236 if (decoder_.get() && !MakeCurrent()) 244 if (decoder_.get() && !MakeCurrent())
237 return; 245 return;
238 if (scheduler_.get()) 246 int64 delay = kHandleMoreWorkPeriodBusyMicroseconds;
239 scheduler_->PollUnscheduleFences(); 247 if (scheduler_.get()) {
240 ScheduleDelayedWork(kHandleMoreWorkPeriodBusyMs); 248 bool fences_complete = scheduler_->PollUnscheduleFences();
249 // Perform idle work if all fences are complete.
250 if (fences_complete) {
251 DCHECK(!last_idle_time_.is_null());
252 base::TimeDelta time_since_idle = base::TimeTicks::Now() -
253 last_idle_time_;
254 base::TimeDelta max_time_since_idle =
255 base::TimeDelta::FromMicroseconds(kMaxTimeSinceIdleMicroseconds);
256
257 // Perform some idle work if idle or it's been too long since
258 // last time we were idle.
259 if (is_idle_ || time_since_idle > max_time_since_idle) {
260 last_idle_time_ = base::TimeTicks::Now();
261 // Use idle work period delay when there's more idle work pending.
262 if (scheduler_->PerformIdleWork())
263 delay = kHandleMoreIdleWorkPeriodBusyMicroseconds;
264 }
265 }
266 }
267 ScheduleDelayedWork(delay);
241 } 268 }
242 269
243 bool GpuCommandBufferStub::HasUnprocessedCommands() { 270 bool GpuCommandBufferStub::HasUnprocessedCommands() {
244 if (command_buffer_.get()) { 271 if (command_buffer_.get()) {
245 gpu::CommandBuffer::State state = command_buffer_->GetLastState(); 272 gpu::CommandBuffer::State state = command_buffer_->GetLastState();
246 return state.put_offset != state.get_offset && 273 return state.put_offset != state.get_offset &&
247 !gpu::error::IsError(state.error); 274 !gpu::error::IsError(state.error);
248 } 275 }
249 return false; 276 return false;
250 } 277 }
251 278
252 void GpuCommandBufferStub::ScheduleDelayedWork(int64 delay) { 279 void GpuCommandBufferStub::ScheduleDelayedWork(int64 delay) {
253 if (HasMoreWork() && !delayed_work_scheduled_) { 280 if (!HasMoreWork()) {
254 delayed_work_scheduled_ = true; 281 last_idle_time_ = base::TimeTicks();
255 MessageLoop::current()->PostDelayedTask( 282 return;
256 FROM_HERE,
257 base::Bind(&GpuCommandBufferStub::PollWork,
258 AsWeakPtr()),
259 base::TimeDelta::FromMilliseconds(delay));
260 } 283 }
284
285 if (delayed_work_scheduled_)
286 return;
287 delayed_work_scheduled_ = true;
288
289 // Consider the command buffer idle if no messages are received between
290 // now and when PollWork is called.
291 is_idle_ = true;
292 if (last_idle_time_.is_null())
293 last_idle_time_ = base::TimeTicks::Now();
294
295 MessageLoop::current()->PostDelayedTask(
296 FROM_HERE,
297 base::Bind(&GpuCommandBufferStub::PollWork,
298 AsWeakPtr()),
299 base::TimeDelta::FromMicroseconds(delay));
261 } 300 }
262 301
263 void GpuCommandBufferStub::OnEcho(const IPC::Message& message) { 302 void GpuCommandBufferStub::OnEcho(const IPC::Message& message) {
264 TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnEcho"); 303 TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnEcho");
265 Send(new IPC::Message(message)); 304 Send(new IPC::Message(message));
266 } 305 }
267 306
268 bool GpuCommandBufferStub::MakeCurrent() { 307 bool GpuCommandBufferStub::MakeCurrent() {
269 if (decoder_->MakeCurrent()) 308 if (decoder_->MakeCurrent())
270 return true; 309 return true;
(...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after
873 if (surface_ && MakeCurrent()) 912 if (surface_ && MakeCurrent())
874 surface_->SetFrontbufferAllocation( 913 surface_->SetFrontbufferAllocation(
875 allocation.browser_allocation.suggest_have_frontbuffer); 914 allocation.browser_allocation.suggest_have_frontbuffer);
876 } 915 }
877 916
878 last_memory_allocation_valid_ = true; 917 last_memory_allocation_valid_ = true;
879 last_memory_allocation_ = allocation; 918 last_memory_allocation_ = allocation;
880 } 919 }
881 920
882 } // namespace content 921 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698