| 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 67e54b17f298a1d92b83526af15808904876d4fc..60dce0568ef1ac2c97531cebe9249feb0bd920ce 100644
|
| --- a/gpu/command_buffer/service/sync_point_manager.cc
|
| +++ b/gpu/command_buffer/service/sync_point_manager.cc
|
| @@ -11,6 +11,7 @@
|
| #include "base/bind.h"
|
| #include "base/location.h"
|
| #include "base/logging.h"
|
| +#include "base/memory/ptr_util.h"
|
| #include "base/memory/ref_counted.h"
|
| #include "base/single_thread_task_runner.h"
|
|
|
| @@ -29,8 +30,26 @@ void RunOnThread(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
|
|
|
| } // namespace
|
|
|
| -scoped_refptr<SyncPointOrderData> SyncPointOrderData::Create() {
|
| - return new SyncPointOrderData;
|
| +SyncPointOrderData::OrderFence::OrderFence(
|
| + uint32_t order,
|
| + uint64_t release,
|
| + const base::Closure& callback,
|
| + scoped_refptr<SyncPointClientState> state)
|
| + : order_num(order),
|
| + fence_release(release),
|
| + release_callback(callback),
|
| + client_state(std::move(state)) {}
|
| +
|
| +SyncPointOrderData::OrderFence::OrderFence(const OrderFence& other) = default;
|
| +
|
| +SyncPointOrderData::OrderFence::~OrderFence() {}
|
| +
|
| +SyncPointOrderData::SyncPointOrderData(SyncPointManager* sync_point_manager,
|
| + SequenceId sequence_id)
|
| + : sync_point_manager_(sync_point_manager), sequence_id_(sequence_id) {}
|
| +
|
| +SyncPointOrderData::~SyncPointOrderData() {
|
| + DCHECK(destroyed_);
|
| }
|
|
|
| void SyncPointOrderData::Destroy() {
|
| @@ -38,20 +57,23 @@ void SyncPointOrderData::Destroy() {
|
| // SyncPointClientState, we must remove the references on destroy. Releasing
|
| // the fence syncs in the order fence queue would be redundant at this point
|
| // because they are assumed to be released on the destruction of the
|
| - // SyncPointClient.
|
| - base::AutoLock auto_lock(lock_);
|
| - destroyed_ = true;
|
| - while (!order_fence_queue_.empty()) {
|
| - order_fence_queue_.pop();
|
| + // SyncPointClientState.
|
| + {
|
| + base::AutoLock auto_lock(lock_);
|
| + DCHECK(!destroyed_);
|
| + destroyed_ = true;
|
| + while (!order_fence_queue_.empty())
|
| + order_fence_queue_.pop();
|
| }
|
| + // Call DestroyedSyncPointOrderData outside the lock to prevent deadlock.
|
| + sync_point_manager_->DestroyedSyncPointOrderData(sequence_id_);
|
| }
|
|
|
| -uint32_t SyncPointOrderData::GenerateUnprocessedOrderNumber(
|
| - SyncPointManager* sync_point_manager) {
|
| - const uint32_t order_num = sync_point_manager->GenerateOrderNumber();
|
| +uint32_t SyncPointOrderData::GenerateUnprocessedOrderNumber() {
|
| base::AutoLock auto_lock(lock_);
|
| - unprocessed_order_num_ = order_num;
|
| - return order_num;
|
| + DCHECK(!destroyed_);
|
| + unprocessed_order_num_ = sync_point_manager_->GenerateOrderNumber();
|
| + return unprocessed_order_num_;
|
| }
|
|
|
| void SyncPointOrderData::BeginProcessingOrderNumber(uint32_t order_num) {
|
| @@ -127,24 +149,6 @@ void SyncPointOrderData::FinishProcessingOrderNumber(uint32_t order_num) {
|
| }
|
| }
|
|
|
| -SyncPointOrderData::OrderFence::OrderFence(
|
| - uint32_t order,
|
| - uint64_t release,
|
| - const base::Closure& callback,
|
| - scoped_refptr<SyncPointClientState> state)
|
| - : order_num(order),
|
| - fence_release(release),
|
| - release_callback(callback),
|
| - client_state(std::move(state)) {}
|
| -
|
| -SyncPointOrderData::OrderFence::OrderFence(const OrderFence& other) = default;
|
| -
|
| -SyncPointOrderData::OrderFence::~OrderFence() {}
|
| -
|
| -SyncPointOrderData::SyncPointOrderData() {}
|
| -
|
| -SyncPointOrderData::~SyncPointOrderData() {}
|
| -
|
| bool SyncPointOrderData::ValidateReleaseOrderNumber(
|
| scoped_refptr<SyncPointClientState> client_state,
|
| uint32_t wait_order_num,
|
| @@ -184,10 +188,48 @@ SyncPointClientState::ReleaseCallback::ReleaseCallback(
|
| SyncPointClientState::ReleaseCallback::~ReleaseCallback() {}
|
|
|
| SyncPointClientState::SyncPointClientState(
|
| - scoped_refptr<SyncPointOrderData> order_data)
|
| - : order_data_(std::move(order_data)) {}
|
| + SyncPointManager* sync_point_manager,
|
| + scoped_refptr<SyncPointOrderData> order_data,
|
| + CommandBufferNamespace namespace_id,
|
| + CommandBufferId command_buffer_id)
|
| + : sync_point_manager_(sync_point_manager),
|
| + order_data_(std::move(order_data)),
|
| + namespace_id_(namespace_id),
|
| + command_buffer_id_(command_buffer_id) {}
|
| +
|
| +SyncPointClientState::~SyncPointClientState() {
|
| + DCHECK_EQ(UINT64_MAX, fence_sync_release_);
|
| +}
|
| +
|
| +void SyncPointClientState::Destroy() {
|
| + // Release all fences on destruction.
|
| + ReleaseFenceSyncHelper(UINT64_MAX);
|
| + DCHECK(sync_point_manager_); // not destroyed
|
| + sync_point_manager_->DestroyedSyncPointClientState(namespace_id_,
|
| + command_buffer_id_);
|
| + sync_point_manager_ = nullptr;
|
| +}
|
| +
|
| +bool SyncPointClientState::Wait(const SyncToken& sync_token,
|
| + const base::Closure& callback) {
|
| + DCHECK(sync_point_manager_); // not destroyed
|
| + // Validate that this Wait call is between BeginProcessingOrderNumber() and
|
| + // FinishProcessingOrderNumber(), or else we may deadlock.
|
| + DCHECK(order_data_->IsProcessingOrderNumber());
|
| + if (sync_token.namespace_id() == namespace_id_ &&
|
| + sync_token.command_buffer_id() == command_buffer_id_) {
|
| + return false;
|
| + }
|
| + uint32_t wait_order_number = order_data_->current_order_num();
|
| + return sync_point_manager_->Wait(sync_token, wait_order_number, callback);
|
| +}
|
|
|
| -SyncPointClientState::~SyncPointClientState() {}
|
| +bool SyncPointClientState::WaitNonThreadSafe(
|
| + const SyncToken& sync_token,
|
| + scoped_refptr<base::SingleThreadTaskRunner> task_runner,
|
| + const base::Closure& callback) {
|
| + return Wait(sync_token, base::Bind(&RunOnThread, task_runner, callback));
|
| +}
|
|
|
| bool SyncPointClientState::IsFenceSyncReleased(uint64_t release) {
|
| base::AutoLock lock(fence_sync_lock_);
|
| @@ -214,6 +256,13 @@ bool SyncPointClientState::WaitForRelease(uint64_t release,
|
| }
|
|
|
| void SyncPointClientState::ReleaseFenceSync(uint64_t release) {
|
| + // Validate that this Release call is between BeginProcessingOrderNumber() and
|
| + // FinishProcessingOrderNumber(), or else we may deadlock.
|
| + DCHECK(order_data_->IsProcessingOrderNumber());
|
| + ReleaseFenceSyncHelper(release);
|
| +}
|
| +
|
| +void SyncPointClientState::ReleaseFenceSyncHelper(uint64_t release) {
|
| // Call callbacks without the lock to avoid possible deadlocks.
|
| std::vector<base::Closure> callback_list;
|
| {
|
| @@ -230,9 +279,8 @@ void SyncPointClientState::ReleaseFenceSync(uint64_t release) {
|
| }
|
| }
|
|
|
| - for (const base::Closure& closure : callback_list) {
|
| + for (const base::Closure& closure : callback_list)
|
| closure.Run();
|
| - }
|
| }
|
|
|
| void SyncPointClientState::EnsureWaitReleased(uint64_t release,
|
| @@ -273,60 +321,63 @@ void SyncPointClientState::EnsureWaitReleased(uint64_t release,
|
| }
|
| }
|
|
|
| -SyncPointClient::SyncPointClient(SyncPointManager* sync_point_manager,
|
| - scoped_refptr<SyncPointOrderData> order_data,
|
| - CommandBufferNamespace namespace_id,
|
| - CommandBufferId command_buffer_id)
|
| - : sync_point_manager_(sync_point_manager),
|
| - order_data_(std::move(order_data)),
|
| - client_state_(new SyncPointClientState(order_data_)),
|
| - namespace_id_(namespace_id),
|
| - command_buffer_id_(command_buffer_id) {
|
| - sync_point_manager_->RegisterSyncPointClient(client_state_, namespace_id,
|
| - command_buffer_id);
|
| +SyncPointManager::SyncPointManager() {
|
| + order_num_generator_.GetNext();
|
| }
|
|
|
| -SyncPointClient::~SyncPointClient() {
|
| - // Release all fences on destruction.
|
| - client_state_->ReleaseFenceSync(UINT64_MAX);
|
| - sync_point_manager_->DeregisterSyncPointClient(namespace_id_,
|
| - command_buffer_id_);
|
| +SyncPointManager::~SyncPointManager() {
|
| + DCHECK(order_data_map_.empty());
|
| + for (const ClientStateMap& client_state_map : client_state_maps_)
|
| + DCHECK(client_state_map.empty());
|
| }
|
|
|
| -bool SyncPointClient::Wait(const SyncToken& sync_token,
|
| - const base::Closure& callback) {
|
| - // Validate that this Wait call is between BeginProcessingOrderNumber() and
|
| - // FinishProcessingOrderNumber(), or else we may deadlock.
|
| - DCHECK(order_data_->IsProcessingOrderNumber());
|
| - if (sync_token.namespace_id() == namespace_id_ &&
|
| - sync_token.command_buffer_id() == command_buffer_id_) {
|
| - return false;
|
| - }
|
| - uint32_t wait_order_number = order_data_->current_order_num();
|
| - return sync_point_manager_->Wait(sync_token, wait_order_number, callback);
|
| +scoped_refptr<SyncPointOrderData> SyncPointManager::CreateSyncPointOrderData() {
|
| + base::AutoLock auto_lock(lock_);
|
| + SequenceId sequence_id = SequenceId::FromUnsafeValue(next_sequence_id_++);
|
| + scoped_refptr<SyncPointOrderData> order_data =
|
| + new SyncPointOrderData(this, sequence_id);
|
| + DCHECK(!order_data_map_.count(sequence_id));
|
| + order_data_map_.insert(std::make_pair(sequence_id, order_data));
|
| + return order_data;
|
| }
|
|
|
| -bool SyncPointClient::WaitNonThreadSafe(
|
| - const SyncToken& sync_token,
|
| - scoped_refptr<base::SingleThreadTaskRunner> task_runner,
|
| - const base::Closure& callback) {
|
| - return Wait(sync_token, base::Bind(&RunOnThread, task_runner, callback));
|
| +void SyncPointManager::DestroyedSyncPointOrderData(SequenceId sequence_id) {
|
| + base::AutoLock auto_lock(lock_);
|
| + DCHECK(order_data_map_.count(sequence_id));
|
| + order_data_map_.erase(sequence_id);
|
| }
|
|
|
| -void SyncPointClient::ReleaseFenceSync(uint64_t release) {
|
| - // Validate that this Release call is between BeginProcessingOrderNumber() and
|
| - // FinishProcessingOrderNumber(), or else we may deadlock.
|
| - DCHECK(order_data_->IsProcessingOrderNumber());
|
| - client_state_->ReleaseFenceSync(release);
|
| -}
|
| +scoped_refptr<SyncPointClientState>
|
| +SyncPointManager::CreateSyncPointClientState(
|
| + CommandBufferNamespace namespace_id,
|
| + CommandBufferId command_buffer_id,
|
| + SequenceId sequence_id) {
|
| + scoped_refptr<SyncPointOrderData> order_data =
|
| + GetSyncPointOrderData(sequence_id);
|
|
|
| -SyncPointManager::SyncPointManager() {
|
| - global_order_num_.GetNext();
|
| + scoped_refptr<SyncPointClientState> client_state = new SyncPointClientState(
|
| + this, order_data, namespace_id, command_buffer_id);
|
| +
|
| + {
|
| + base::AutoLock auto_lock(lock_);
|
| + DCHECK_GE(namespace_id, 0);
|
| + DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_state_maps_));
|
| + DCHECK(!client_state_maps_[namespace_id].count(command_buffer_id));
|
| + client_state_maps_[namespace_id].insert(
|
| + std::make_pair(command_buffer_id, client_state));
|
| + }
|
| +
|
| + return client_state;
|
| }
|
|
|
| -SyncPointManager::~SyncPointManager() {
|
| - for (const ClientStateMap& client_state_map : client_state_maps_)
|
| - DCHECK(client_state_map.empty());
|
| +void SyncPointManager::DestroyedSyncPointClientState(
|
| + CommandBufferNamespace namespace_id,
|
| + CommandBufferId command_buffer_id) {
|
| + base::AutoLock auto_lock(lock_);
|
| + DCHECK_GE(namespace_id, 0);
|
| + DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_state_maps_));
|
| + DCHECK(client_state_maps_[namespace_id].count(command_buffer_id));
|
| + client_state_maps_[namespace_id].erase(command_buffer_id);
|
| }
|
|
|
| bool SyncPointManager::IsSyncTokenReleased(const SyncToken& sync_token) {
|
| @@ -337,6 +388,35 @@ bool SyncPointManager::IsSyncTokenReleased(const SyncToken& sync_token) {
|
| return true;
|
| }
|
|
|
| +SequenceId SyncPointManager::GetSyncTokenReleaseSequenceId(
|
| + const SyncToken& sync_token) {
|
| + scoped_refptr<SyncPointClientState> client_state = GetSyncPointClientState(
|
| + sync_token.namespace_id(), sync_token.command_buffer_id());
|
| + if (client_state)
|
| + return client_state->sequence_id();
|
| + return SequenceId();
|
| +}
|
| +
|
| +uint32_t SyncPointManager::GetProcessedOrderNum() const {
|
| + base::AutoLock auto_lock(lock_);
|
| + uint32_t processed_order_num = 0;
|
| + for (const auto& kv : order_data_map_) {
|
| + processed_order_num =
|
| + std::max(processed_order_num, kv.second->processed_order_num());
|
| + }
|
| + return processed_order_num;
|
| +}
|
| +
|
| +uint32_t SyncPointManager::GetUnprocessedOrderNum() const {
|
| + base::AutoLock auto_lock(lock_);
|
| + uint32_t unprocessed_order_num = 0;
|
| + for (const auto& kv : order_data_map_) {
|
| + unprocessed_order_num =
|
| + std::max(unprocessed_order_num, kv.second->unprocessed_order_num());
|
| + }
|
| + return unprocessed_order_num;
|
| +}
|
| +
|
| bool SyncPointManager::Wait(const SyncToken& sync_token,
|
| uint32_t wait_order_num,
|
| const base::Closure& callback) {
|
| @@ -376,32 +456,8 @@ bool SyncPointManager::WaitOutOfOrderNonThreadSafe(
|
| base::Bind(&RunOnThread, task_runner, callback));
|
| }
|
|
|
| -void SyncPointManager::RegisterSyncPointClient(
|
| - scoped_refptr<SyncPointClientState> client_state,
|
| - CommandBufferNamespace namespace_id,
|
| - CommandBufferId command_buffer_id) {
|
| - DCHECK_GE(namespace_id, 0);
|
| - DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_state_maps_));
|
| -
|
| - base::AutoLock auto_lock(client_state_maps_lock_);
|
| - DCHECK(!client_state_maps_[namespace_id].count(command_buffer_id));
|
| - client_state_maps_[namespace_id].insert(
|
| - std::make_pair(command_buffer_id, std::move(client_state)));
|
| -}
|
| -
|
| -void SyncPointManager::DeregisterSyncPointClient(
|
| - CommandBufferNamespace namespace_id,
|
| - CommandBufferId command_buffer_id) {
|
| - DCHECK_GE(namespace_id, 0);
|
| - DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_state_maps_));
|
| -
|
| - base::AutoLock auto_lock(client_state_maps_lock_);
|
| - DCHECK(client_state_maps_[namespace_id].count(command_buffer_id));
|
| - client_state_maps_[namespace_id].erase(command_buffer_id);
|
| -}
|
| -
|
| uint32_t SyncPointManager::GenerateOrderNumber() {
|
| - return global_order_num_.GetNext();
|
| + return order_num_generator_.GetNext();
|
| }
|
|
|
| scoped_refptr<SyncPointClientState> SyncPointManager::GetSyncPointClientState(
|
| @@ -409,7 +465,7 @@ scoped_refptr<SyncPointClientState> SyncPointManager::GetSyncPointClientState(
|
| CommandBufferId command_buffer_id) {
|
| if (namespace_id >= 0) {
|
| DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_state_maps_));
|
| - base::AutoLock auto_lock(client_state_maps_lock_);
|
| + base::AutoLock auto_lock(lock_);
|
| ClientStateMap& client_state_map = client_state_maps_[namespace_id];
|
| auto it = client_state_map.find(command_buffer_id);
|
| if (it != client_state_map.end())
|
| @@ -418,4 +474,13 @@ scoped_refptr<SyncPointClientState> SyncPointManager::GetSyncPointClientState(
|
| return nullptr;
|
| }
|
|
|
| +scoped_refptr<SyncPointOrderData> SyncPointManager::GetSyncPointOrderData(
|
| + SequenceId sequence_id) {
|
| + base::AutoLock auto_lock(lock_);
|
| + auto it = order_data_map_.find(sequence_id);
|
| + if (it != order_data_map_.end())
|
| + return it->second;
|
| + return nullptr;
|
| +}
|
| +
|
| } // namespace gpu
|
|
|