| Index: gpu/command_buffer/service/sync_point_manager.cc
|
| diff --git a/gpu/command_buffer/service/sync_point_manager.cc b/gpu/command_buffer/service/sync_point_manager.cc
|
| index 039e494de8b1d4bd5ea3df100c89ec10cb508690..ade353c7d260828347b7d95e18693bea924114fe 100644
|
| --- a/gpu/command_buffer/service/sync_point_manager.cc
|
| +++ b/gpu/command_buffer/service/sync_point_manager.cc
|
| @@ -25,19 +25,136 @@ uint32_t SyncPointClientState::GenerateUnprocessedOrderNumber(
|
| return order_num;
|
| }
|
|
|
| +void SyncPointClientState::BeginProcessingOrderNumber(uint32_t order_num) {
|
| + DCHECK(processing_thread_checker_.CalledOnValidThread());
|
| + DCHECK_GE(order_num, current_order_num_);
|
| + current_order_num_ = order_num;
|
| +}
|
| +
|
| +void SyncPointClientState::FinishProcessingOrderNumber(uint32_t order_num) {
|
| + DCHECK(processing_thread_checker_.CalledOnValidThread());
|
| + DCHECK_EQ(current_order_num_, order_num);
|
| + DCHECK_GT(order_num, processed_order_num());
|
| +
|
| + // Catch invalid waits which were waiting on fence syncs that do not exist.
|
| + uint32_t invalid_release = 0;
|
| + {
|
| + base::AutoLock auto_lock(fence_sync_lock_);
|
| + uint32_t highest_wait_release = 0;
|
| + while (!order_fence_queue_.empty() &&
|
| + order_fence_queue_.top().order_num <= order_num) {
|
| + const uint32_t fence_release = order_fence_queue_.top().fence_release;
|
| + highest_wait_release = std::max(highest_wait_release, fence_release);
|
| + order_fence_queue_.pop();
|
| + }
|
| +
|
| + if (highest_wait_release > fence_sync_release_) {
|
| + invalid_release = fence_sync_release_;
|
| + }
|
| + }
|
| +
|
| + if (invalid_release) {
|
| + // Bad wait for release that doesn't exist, release all waits up to here.
|
| + ReleaseFenceSync(invalid_release);
|
| + }
|
| +
|
| + base::subtle::Release_Store(&processed_order_num_, order_num);
|
| +}
|
| +
|
| SyncPointClientState::SyncPointClientState()
|
| : processed_order_num_(0),
|
| unprocessed_order_num_(0),
|
| - current_order_num_(0) {
|
| + current_order_num_(0),
|
| + fence_sync_release_(0) {
|
| }
|
|
|
| SyncPointClientState::~SyncPointClientState() {
|
| + // Release all fences on destruction.
|
| + ReleaseFenceSync(UINT32_MAX);
|
| +}
|
| +
|
| +SyncPointClientState::ReleaseCallback::ReleaseCallback(
|
| + uint32_t release, const base::Closure& callback)
|
| + : release_count(release),
|
| + callback_closure(callback) {
|
| +}
|
| +
|
| +SyncPointClientState::ReleaseCallback::~ReleaseCallback() {
|
| +}
|
| +
|
| +bool SyncPointClientState::WaitForRelease(uint32_t wait_order_num,
|
| + uint32_t release,
|
| + const base::Closure& callback) {
|
| + // Lock must be held the whole time while we validate otherwise it could be
|
| + // released while we are checking.
|
| + {
|
| + base::AutoLock auto_lock(fence_sync_lock_);
|
| + if (release > fence_sync_release_) {
|
| + const uint32_t processed_num = processed_order_num();
|
| + const uint32_t unprocessed_num = unprocessed_order_num();
|
| +
|
| + // Release should have a lower order number than wait order number.
|
| + if (processed_num > wait_order_num)
|
| + return false;
|
| +
|
| + // Release should have more unprocessed numbers if we are waiting.
|
| + if (unprocessed_num > processed_num)
|
| + return false;
|
| +
|
| + // Add the callback which will be called upon release.
|
| + release_callback_queue_.push(ReleaseCallback(release, callback));
|
| +
|
| + // Validate by ensuring fence is released by the expected order number.
|
| + const uint32_t expected_order_num = std::min(unprocessed_num,
|
| + wait_order_num);
|
| + order_fence_queue_.push(OrderFence(expected_order_num, release));
|
| +
|
| + return true;
|
| + }
|
| + }
|
| +
|
| + // Already released, run the callback now.
|
| + callback.Run();
|
| + return true;
|
| +}
|
| +
|
| +void SyncPointClientState::ReleaseFenceSync(uint32_t release) {
|
| + // Call callbacks without the lock to avoid possible deadlocks.
|
| + std::vector<base::Closure> callback_list;
|
| + {
|
| + base::AutoLock auto_lock(fence_sync_lock_);
|
| + DCHECK_GT(release, fence_sync_release_);
|
| + fence_sync_release_ = release;
|
| +
|
| + while (!release_callback_queue_.empty() &&
|
| + release_callback_queue_.top().release_count <= release) {
|
| + callback_list.push_back(release_callback_queue_.top().callback_closure);
|
| + release_callback_queue_.pop();
|
| + }
|
| + }
|
| +
|
| + for (const base::Closure& closure : callback_list) {
|
| + closure.Run();
|
| + }
|
| }
|
|
|
| SyncPointClient::~SyncPointClient() {
|
| sync_point_manager_->DestroySyncPointClient(namespace_id_, client_id_);
|
| }
|
|
|
| +bool SyncPointClient::Wait(scoped_refptr<SyncPointClientState> release_state,
|
| + uint32_t release_count,
|
| + const base::Closure& wait_complete_callback) {
|
| + const uint32_t wait_order_number = client_state_->current_order_num();
|
| + return release_state->WaitForRelease(wait_order_number,
|
| + release_count,
|
| + wait_complete_callback);
|
| +}
|
| +
|
| +void SyncPointClient::ReleaseFenceSync(uint32_t release) {
|
| + client_state_->ReleaseFenceSync(release);
|
| +}
|
| +
|
| SyncPointClient::SyncPointClient(SyncPointManager* sync_point_manager,
|
| scoped_refptr<SyncPointClientState> state,
|
| CommandBufferNamespace namespace_id,
|
|
|