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

Side by Side Diff: gpu/command_buffer/service/sync_point_manager.cc

Issue 2722883002: gpu: Allow waiting on sync tokens without sync token client. (Closed)
Patch Set: review Created 3 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
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 "gpu/command_buffer/service/sync_point_manager.h" 5 #include "gpu/command_buffer/service/sync_point_manager.h"
6 6
7 #include <limits.h> 7 #include <limits.h>
8 #include <stddef.h> 8 #include <stddef.h>
9 #include <stdint.h> 9 #include <stdint.h>
10 10
11 #include <climits>
12
13 #include "base/bind.h" 11 #include "base/bind.h"
14 #include "base/containers/hash_tables.h"
15 #include "base/location.h" 12 #include "base/location.h"
16 #include "base/logging.h" 13 #include "base/logging.h"
17 #include "base/memory/ptr_util.h" 14 #include "base/memory/ref_counted.h"
18 #include "base/rand_util.h"
19 #include "base/sequence_checker.h"
20 #include "base/single_thread_task_runner.h" 15 #include "base/single_thread_task_runner.h"
21 16
22 namespace gpu { 17 namespace gpu {
23 18
24 namespace { 19 namespace {
25 20
26 void RunOnThread(scoped_refptr<base::SingleThreadTaskRunner> task_runner, 21 void RunOnThread(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
27 const base::Closure& callback) { 22 const base::Closure& callback) {
28 if (task_runner->BelongsToCurrentThread()) { 23 if (task_runner->BelongsToCurrentThread()) {
29 callback.Run(); 24 callback.Run();
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 scoped_refptr<SyncPointClientState> state) 134 scoped_refptr<SyncPointClientState> state)
140 : order_num(order), 135 : order_num(order),
141 fence_release(release), 136 fence_release(release),
142 release_callback(callback), 137 release_callback(callback),
143 client_state(state) {} 138 client_state(state) {}
144 139
145 SyncPointOrderData::OrderFence::OrderFence(const OrderFence& other) = default; 140 SyncPointOrderData::OrderFence::OrderFence(const OrderFence& other) = default;
146 141
147 SyncPointOrderData::OrderFence::~OrderFence() {} 142 SyncPointOrderData::OrderFence::~OrderFence() {}
148 143
149 SyncPointOrderData::SyncPointOrderData() 144 SyncPointOrderData::SyncPointOrderData() {}
150 : current_order_num_(0),
151 paused_(false),
152 destroyed_(false),
153 processed_order_num_(0),
154 unprocessed_order_num_(0) {}
155 145
156 SyncPointOrderData::~SyncPointOrderData() {} 146 SyncPointOrderData::~SyncPointOrderData() {}
157 147
158 bool SyncPointOrderData::ValidateReleaseOrderNumber( 148 bool SyncPointOrderData::ValidateReleaseOrderNumber(
159 scoped_refptr<SyncPointClientState> client_state, 149 scoped_refptr<SyncPointClientState> client_state,
160 uint32_t wait_order_num, 150 uint32_t wait_order_num,
161 uint64_t fence_release, 151 uint64_t fence_release,
162 const base::Closure& release_callback) { 152 const base::Closure& release_callback) {
163 base::AutoLock auto_lock(lock_); 153 base::AutoLock auto_lock(lock_);
164 if (destroyed_) 154 if (destroyed_)
165 return false; 155 return false;
166 156
167 // Release should have a possible unprocessed order number lower 157 // Release should have a possible unprocessed order number lower than the wait
168 // than the wait order number. 158 // order number.
169 if ((processed_order_num_ + 1) >= wait_order_num) 159 if ((processed_order_num_ + 1) >= wait_order_num)
170 return false; 160 return false;
171 161
172 // Release should have more unprocessed numbers if we are waiting. 162 // Release should have more unprocessed numbers if we are waiting.
173 if (unprocessed_order_num_ <= processed_order_num_) 163 if (unprocessed_order_num_ <= processed_order_num_)
174 return false; 164 return false;
175 165
176 // So far it could be valid, but add an order fence guard to be sure it 166 // So far it could be valid, but add an order fence guard to be sure it
177 // gets released eventually. 167 // gets released eventually.
178 const uint32_t expected_order_num = 168 uint32_t expected_order_num =
179 std::min(unprocessed_order_num_, wait_order_num); 169 std::min(unprocessed_order_num_, wait_order_num);
180 order_fence_queue_.push(OrderFence(expected_order_num, fence_release, 170 order_fence_queue_.push(OrderFence(expected_order_num, fence_release,
181 release_callback, client_state)); 171 release_callback, client_state));
182 return true; 172 return true;
183 } 173 }
184 174
185 SyncPointClientState::ReleaseCallback::ReleaseCallback( 175 SyncPointClientState::ReleaseCallback::ReleaseCallback(
186 uint64_t release, 176 uint64_t release,
187 const base::Closure& callback) 177 const base::Closure& callback)
188 : release_count(release), callback_closure(callback) {} 178 : release_count(release), callback_closure(callback) {}
189 179
190 SyncPointClientState::ReleaseCallback::ReleaseCallback( 180 SyncPointClientState::ReleaseCallback::ReleaseCallback(
191 const ReleaseCallback& other) = default; 181 const ReleaseCallback& other) = default;
192 182
193 SyncPointClientState::ReleaseCallback::~ReleaseCallback() {} 183 SyncPointClientState::ReleaseCallback::~ReleaseCallback() {}
194 184
195 SyncPointClientState::SyncPointClientState( 185 SyncPointClientState::SyncPointClientState(
196 scoped_refptr<SyncPointOrderData> order_data) 186 scoped_refptr<SyncPointOrderData> order_data)
197 : order_data_(order_data), fence_sync_release_(0) {} 187 : order_data_(order_data) {}
198 188
199 SyncPointClientState::~SyncPointClientState() { 189 SyncPointClientState::~SyncPointClientState() {}
190
191 bool SyncPointClientState::IsFenceSyncReleased(uint64_t release) {
192 base::AutoLock lock(fence_sync_lock_);
193 return release <= fence_sync_release_;
200 } 194 }
201 195
202 bool SyncPointClientState::WaitForRelease(CommandBufferNamespace namespace_id, 196 bool SyncPointClientState::WaitForRelease(uint64_t release,
203 CommandBufferId client_id,
204 uint32_t wait_order_num, 197 uint32_t wait_order_num,
205 uint64_t release,
206 const base::Closure& callback) { 198 const base::Closure& callback) {
207 // Lock must be held the whole time while we validate otherwise it could be 199 // Lock must be held the whole time while we validate otherwise it could be
208 // released while we are checking. 200 // released while we are checking.
209 { 201 {
210 base::AutoLock auto_lock(fence_sync_lock_); 202 base::AutoLock auto_lock(fence_sync_lock_);
211 if (release > fence_sync_release_) { 203 if (release > fence_sync_release_ &&
212 if (!order_data_->ValidateReleaseOrderNumber(this, wait_order_num, 204 order_data_->ValidateReleaseOrderNumber(this, wait_order_num, release,
213 release, callback)) { 205 callback)) {
214 return false; 206 // Add the callback which will be called upon release.
215 } else { 207 release_callback_queue_.push(ReleaseCallback(release, callback));
216 // Add the callback which will be called upon release. 208 return true;
217 release_callback_queue_.push(ReleaseCallback(release, callback));
218 if (!on_wait_callback_.is_null())
219 on_wait_callback_.Run(namespace_id, client_id);
220 return true;
221 }
222 } 209 }
223 } 210 }
224 211 // Already released, do not run the callback.
225 // Already released, run the callback now. 212 return false;
226 callback.Run();
227 return true;
228 } 213 }
229 214
230 void SyncPointClientState::ReleaseFenceSync(uint64_t release) { 215 void SyncPointClientState::ReleaseFenceSync(uint64_t release) {
231 // Call callbacks without the lock to avoid possible deadlocks. 216 // Call callbacks without the lock to avoid possible deadlocks.
232 std::vector<base::Closure> callback_list; 217 std::vector<base::Closure> callback_list;
233 { 218 {
234 base::AutoLock auto_lock(fence_sync_lock_); 219 base::AutoLock auto_lock(fence_sync_lock_);
220
235 DLOG_IF(ERROR, release <= fence_sync_release_) 221 DLOG_IF(ERROR, release <= fence_sync_release_)
236 << "Client submitted fence releases out of order."; 222 << "Client submitted fence releases out of order.";
223 fence_sync_release_ = release;
237 224
238 fence_sync_release_ = release;
239 while (!release_callback_queue_.empty() && 225 while (!release_callback_queue_.empty() &&
240 release_callback_queue_.top().release_count <= release) { 226 release_callback_queue_.top().release_count <= release) {
241 callback_list.push_back(release_callback_queue_.top().callback_closure); 227 callback_list.push_back(release_callback_queue_.top().callback_closure);
242 release_callback_queue_.pop(); 228 release_callback_queue_.pop();
243 } 229 }
244 } 230 }
245 231
246 for (const base::Closure& closure : callback_list) { 232 for (const base::Closure& closure : callback_list) {
247 closure.Run(); 233 closure.Run();
248 } 234 }
(...skipping 30 matching lines...) Expand all
279 release_callback_queue_.push(popped_callback); 265 release_callback_queue_.push(popped_callback);
280 } 266 }
281 } 267 }
282 268
283 if (call_callback) { 269 if (call_callback) {
284 // This effectively releases the wait without releasing the fence. 270 // This effectively releases the wait without releasing the fence.
285 callback.Run(); 271 callback.Run();
286 } 272 }
287 } 273 }
288 274
289 void SyncPointClientState::SetOnWaitCallback(const OnWaitCallback& callback) { 275 SyncPointClient::SyncPointClient(SyncPointManager* sync_point_manager,
290 on_wait_callback_ = callback; 276 scoped_refptr<SyncPointOrderData> order_data,
277 CommandBufferNamespace namespace_id,
278 CommandBufferId command_buffer_id)
279 : sync_point_manager_(sync_point_manager),
280 order_data_(order_data),
281 client_state_(new SyncPointClientState(order_data)),
282 namespace_id_(namespace_id),
283 command_buffer_id_(command_buffer_id) {
284 sync_point_manager_->RegisterSyncPointClient(client_state_, namespace_id,
285 command_buffer_id);
291 } 286 }
292 287
293 SyncPointClient::~SyncPointClient() { 288 SyncPointClient::~SyncPointClient() {
294 if (namespace_id_ != gpu::CommandBufferNamespace::INVALID) { 289 // Release all fences on destruction.
295 // Release all fences on destruction. 290 client_state_->ReleaseFenceSync(UINT64_MAX);
296 client_state_->ReleaseFenceSync(UINT64_MAX); 291 sync_point_manager_->DeregisterSyncPointClient(namespace_id_,
297 292 command_buffer_id_);
298 sync_point_manager_->DestroySyncPointClient(namespace_id_, client_id_);
299 }
300 } 293 }
301 294
302 bool SyncPointClient::Wait(SyncPointClientState* release_state, 295 bool SyncPointClient::Wait(const SyncToken& sync_token,
303 uint64_t release_count, 296 const base::Closure& callback) {
304 const base::Closure& wait_complete_callback) {
305 // Validate that this Wait call is between BeginProcessingOrderNumber() and 297 // Validate that this Wait call is between BeginProcessingOrderNumber() and
306 // FinishProcessingOrderNumber(), or else we may deadlock. 298 // FinishProcessingOrderNumber(), or else we may deadlock.
307 DCHECK(client_state_->order_data()->IsProcessingOrderNumber()); 299 DCHECK(order_data_->IsProcessingOrderNumber());
308 300 if (sync_token.namespace_id() == namespace_id_ &&
309 const uint32_t wait_order_number = 301 sync_token.command_buffer_id() == command_buffer_id_) {
310 client_state_->order_data()->current_order_num();
311
312 // If waiting on self or wait was invalid, call the callback and return false.
313 if (client_state_ == release_state ||
314 !release_state->WaitForRelease(namespace_id_, client_id_,
315 wait_order_number, release_count,
316 wait_complete_callback)) {
317 wait_complete_callback.Run();
318 return false; 302 return false;
319 } 303 }
320 return true; 304 uint32_t wait_order_number = order_data_->current_order_num();
305 return sync_point_manager_->Wait(sync_token, wait_order_number, callback);
321 } 306 }
322 307
323 bool SyncPointClient::WaitNonThreadSafe( 308 bool SyncPointClient::WaitNonThreadSafe(
324 SyncPointClientState* release_state, 309 const SyncToken& sync_token,
325 uint64_t release_count, 310 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
326 scoped_refptr<base::SingleThreadTaskRunner> runner, 311 const base::Closure& callback) {
327 const base::Closure& wait_complete_callback) { 312 return Wait(sync_token, base::Bind(&RunOnThread, task_runner, callback));
328 return Wait(release_state, release_count,
329 base::Bind(&RunOnThread, runner, wait_complete_callback));
330 }
331
332 bool SyncPointClient::WaitOutOfOrder(
333 SyncPointClientState* release_state,
334 uint64_t release_count,
335 const base::Closure& wait_complete_callback) {
336 // Validate that this Wait call is not between BeginProcessingOrderNumber()
337 // and FinishProcessingOrderNumber(), or else we may deadlock.
338 DCHECK(!client_state_ ||
339 !client_state_->order_data()->IsProcessingOrderNumber());
340
341 // No order number associated with the current execution context, using
342 // UINT32_MAX will just assume the release is in the SyncPointClientState's
343 // order numbers to be executed.
344 if (!release_state->WaitForRelease(namespace_id_, client_id_, UINT32_MAX,
345 release_count, wait_complete_callback)) {
346 wait_complete_callback.Run();
347 return false;
348 }
349 return true;
350 }
351
352 bool SyncPointClient::WaitOutOfOrderNonThreadSafe(
353 SyncPointClientState* release_state,
354 uint64_t release_count,
355 scoped_refptr<base::SingleThreadTaskRunner> runner,
356 const base::Closure& wait_complete_callback) {
357 return WaitOutOfOrder(
358 release_state, release_count,
359 base::Bind(&RunOnThread, runner, wait_complete_callback));
360 } 313 }
361 314
362 void SyncPointClient::ReleaseFenceSync(uint64_t release) { 315 void SyncPointClient::ReleaseFenceSync(uint64_t release) {
363 // Validate that this Release call is between BeginProcessingOrderNumber() and 316 // Validate that this Release call is between BeginProcessingOrderNumber() and
364 // FinishProcessingOrderNumber(), or else we may deadlock. 317 // FinishProcessingOrderNumber(), or else we may deadlock.
365 DCHECK(client_state_->order_data()->IsProcessingOrderNumber()); 318 DCHECK(order_data_->IsProcessingOrderNumber());
366 client_state_->ReleaseFenceSync(release); 319 client_state_->ReleaseFenceSync(release);
367 } 320 }
368 321
369 void SyncPointClient::SetOnWaitCallback(const OnWaitCallback& callback) { 322 SyncPointManager::SyncPointManager() {
370 client_state_->SetOnWaitCallback(callback);
371 }
372
373 SyncPointClient::SyncPointClient()
374 : sync_point_manager_(nullptr),
375 namespace_id_(gpu::CommandBufferNamespace::INVALID),
376 client_id_() {}
377
378 SyncPointClient::SyncPointClient(SyncPointManager* sync_point_manager,
379 scoped_refptr<SyncPointOrderData> order_data,
380 CommandBufferNamespace namespace_id,
381 CommandBufferId client_id)
382 : sync_point_manager_(sync_point_manager),
383 client_state_(new SyncPointClientState(order_data)),
384 namespace_id_(namespace_id),
385 client_id_(client_id) {}
386
387 SyncPointManager::SyncPointManager(bool allow_threaded_wait) {
388 global_order_num_.GetNext(); 323 global_order_num_.GetNext();
389 } 324 }
390 325
391 SyncPointManager::~SyncPointManager() { 326 SyncPointManager::~SyncPointManager() {
392 for (const ClientMap& client_map : client_maps_) { 327 for (const ClientStateMap& client_state_map : client_state_maps_)
393 DCHECK(client_map.empty()); 328 DCHECK(client_state_map.empty());
394 }
395 } 329 }
396 330
397 std::unique_ptr<SyncPointClient> SyncPointManager::CreateSyncPointClient( 331 bool SyncPointManager::IsSyncTokenReleased(const SyncToken& sync_token) {
398 scoped_refptr<SyncPointOrderData> order_data, 332 scoped_refptr<SyncPointClientState> release_state = GetSyncPointClientState(
399 CommandBufferNamespace namespace_id, 333 sync_token.namespace_id(), sync_token.command_buffer_id());
400 CommandBufferId client_id) { 334 if (release_state)
401 DCHECK_GE(namespace_id, 0); 335 return release_state->IsFenceSyncReleased(sync_token.release_count());
402 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_maps_)); 336 return true;
403 base::AutoLock auto_lock(client_maps_lock_);
404
405 ClientMap& client_map = client_maps_[namespace_id];
406 std::pair<ClientMap::iterator, bool> result = client_map.insert(
407 std::make_pair(client_id, new SyncPointClient(this, order_data,
408 namespace_id, client_id)));
409 DCHECK(result.second);
410
411 return base::WrapUnique(result.first->second);
412 } 337 }
413 338
414 std::unique_ptr<SyncPointClient> 339 bool SyncPointManager::Wait(const SyncToken& sync_token,
415 SyncPointManager::CreateSyncPointClientWaiter() { 340 uint32_t wait_order_num,
416 return base::WrapUnique(new SyncPointClient); 341 const base::Closure& callback) {
342 scoped_refptr<SyncPointClientState> release_state = GetSyncPointClientState(
343 sync_token.namespace_id(), sync_token.command_buffer_id());
344 if (release_state &&
345 release_state->WaitForRelease(sync_token.release_count(), wait_order_num,
346 callback)) {
347 return true;
348 }
349 // Do not run callback if wait is invalid.
350 return false;
417 } 351 }
418 352
419 scoped_refptr<SyncPointClientState> SyncPointManager::GetSyncPointClientState( 353 bool SyncPointManager::WaitNonThreadSafe(
354 const SyncToken& sync_token,
355 uint32_t wait_order_num,
356 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
357 const base::Closure& callback) {
358 return Wait(sync_token, wait_order_num,
359 base::Bind(&RunOnThread, task_runner, callback));
360 }
361
362 bool SyncPointManager::WaitOutOfOrder(const SyncToken& trusted_sync_token,
363 const base::Closure& callback) {
364 // No order number associated with the current execution context, using
365 // UINT32_MAX will just assume the release is in the SyncPointClientState's
366 // order numbers to be executed.
367 return Wait(trusted_sync_token, UINT32_MAX, callback);
368 }
369
370 bool SyncPointManager::WaitOutOfOrderNonThreadSafe(
371 const SyncToken& trusted_sync_token,
372 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
373 const base::Closure& callback) {
374 return WaitOutOfOrder(trusted_sync_token,
375 base::Bind(&RunOnThread, task_runner, callback));
376 }
377
378 void SyncPointManager::RegisterSyncPointClient(
379 scoped_refptr<SyncPointClientState> client_state,
420 CommandBufferNamespace namespace_id, 380 CommandBufferNamespace namespace_id,
421 CommandBufferId client_id) { 381 CommandBufferId command_buffer_id) {
422 if (namespace_id >= 0) { 382 DCHECK_GE(namespace_id, 0);
423 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_maps_)); 383 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_state_maps_));
424 base::AutoLock auto_lock(client_maps_lock_); 384
425 ClientMap& client_map = client_maps_[namespace_id]; 385 base::AutoLock auto_lock(client_state_maps_lock_);
426 ClientMap::iterator it = client_map.find(client_id); 386 DCHECK(!client_state_maps_[namespace_id].count(command_buffer_id));
427 if (it != client_map.end()) { 387 client_state_maps_[namespace_id].insert(
428 return it->second->client_state(); 388 std::make_pair(command_buffer_id, client_state));
429 } 389 }
430 } 390
431 return nullptr; 391 void SyncPointManager::DeregisterSyncPointClient(
392 CommandBufferNamespace namespace_id,
393 CommandBufferId command_buffer_id) {
394 DCHECK_GE(namespace_id, 0);
395 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_state_maps_));
396
397 base::AutoLock auto_lock(client_state_maps_lock_);
398 DCHECK(client_state_maps_[namespace_id].count(command_buffer_id));
399 client_state_maps_[namespace_id].erase(command_buffer_id);
432 } 400 }
433 401
434 uint32_t SyncPointManager::GenerateOrderNumber() { 402 uint32_t SyncPointManager::GenerateOrderNumber() {
435 return global_order_num_.GetNext(); 403 return global_order_num_.GetNext();
436 } 404 }
437 405
438 void SyncPointManager::DestroySyncPointClient( 406 scoped_refptr<SyncPointClientState> SyncPointManager::GetSyncPointClientState(
439 CommandBufferNamespace namespace_id, 407 CommandBufferNamespace namespace_id,
440 CommandBufferId client_id) { 408 CommandBufferId command_buffer_id) {
441 DCHECK_GE(namespace_id, 0); 409 if (namespace_id >= 0) {
442 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_maps_)); 410 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_state_maps_));
443 411 base::AutoLock auto_lock(client_state_maps_lock_);
444 base::AutoLock auto_lock(client_maps_lock_); 412 ClientStateMap& client_state_map = client_state_maps_[namespace_id];
445 ClientMap& client_map = client_maps_[namespace_id]; 413 auto it = client_state_map.find(command_buffer_id);
446 ClientMap::iterator it = client_map.find(client_id); 414 if (it != client_state_map.end())
447 DCHECK(it != client_map.end()); 415 return it->second;
448 client_map.erase(it); 416 }
417 return nullptr;
449 } 418 }
450 419
451 } // namespace gpu 420 } // namespace gpu
OLDNEW
« no previous file with comments | « gpu/command_buffer/service/sync_point_manager.h ('k') | gpu/command_buffer/service/sync_point_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698