| Index: gpu/command_buffer/service/sync_point_manager.h
|
| diff --git a/gpu/command_buffer/service/sync_point_manager.h b/gpu/command_buffer/service/sync_point_manager.h
|
| index 7a3695c9886207853dff2f86dffdc98b2bcd1689..a34a17cede443e758d5f453b91f012c4147c11b9 100644
|
| --- a/gpu/command_buffer/service/sync_point_manager.h
|
| +++ b/gpu/command_buffer/service/sync_point_manager.h
|
| @@ -23,6 +23,7 @@
|
| #include "base/threading/thread_checker.h"
|
| #include "gpu/command_buffer/common/command_buffer_id.h"
|
| #include "gpu/command_buffer/common/constants.h"
|
| +#include "gpu/command_buffer/common/sync_token.h"
|
| #include "gpu/gpu_export.h"
|
|
|
| namespace base {
|
| @@ -66,9 +67,14 @@ class GPU_EXPORT SyncPointOrderData
|
| return !paused_ && current_order_num_ > processed_order_num();
|
| }
|
|
|
| + bool ValidateReleaseOrderNumber(
|
| + scoped_refptr<SyncPointClientState> client_state,
|
| + uint32_t wait_order_num,
|
| + uint64_t fence_release,
|
| + const base::Closure& release_callback);
|
| +
|
| private:
|
| friend class base::RefCountedThreadSafe<SyncPointOrderData>;
|
| - friend class SyncPointClientState;
|
|
|
| struct OrderFence {
|
| uint32_t order_num;
|
| @@ -84,32 +90,26 @@ class GPU_EXPORT SyncPointOrderData
|
| ~OrderFence();
|
|
|
| bool operator>(const OrderFence& rhs) const {
|
| - return (order_num > rhs.order_num) ||
|
| - ((order_num == rhs.order_num) &&
|
| - (fence_release > rhs.fence_release));
|
| + return std::tie(order_num, fence_release) >
|
| + std::tie(rhs.order_num, rhs.fence_release);
|
| }
|
| };
|
| typedef std::priority_queue<OrderFence,
|
| std::vector<OrderFence>,
|
| - std::greater<OrderFence>> OrderFenceQueue;
|
| + std::greater<OrderFence>>
|
| + OrderFenceQueue;
|
|
|
| SyncPointOrderData();
|
| ~SyncPointOrderData();
|
|
|
| - bool ValidateReleaseOrderNumber(
|
| - scoped_refptr<SyncPointClientState> client_state,
|
| - uint32_t wait_order_num,
|
| - uint64_t fence_release,
|
| - const base::Closure& release_callback);
|
| -
|
| // Non thread-safe functions need to be called from a single thread.
|
| base::ThreadChecker processing_thread_checker_;
|
|
|
| // Current IPC order number being processed (only used on processing thread).
|
| - uint32_t current_order_num_;
|
| + uint32_t current_order_num_ = 0;
|
|
|
| // Whether or not the current order number is being processed or paused.
|
| - bool paused_;
|
| + bool paused_ = false;
|
|
|
| // This lock protects destroyed_, processed_order_num_,
|
| // unprocessed_order_num_, and order_fence_queue_. All order numbers (n) in
|
| @@ -117,13 +117,13 @@ class GPU_EXPORT SyncPointOrderData
|
| // processed_order_num_ < n <= unprocessed_order_num_.
|
| mutable base::Lock lock_;
|
|
|
| - bool destroyed_;
|
| + bool destroyed_ = false;
|
|
|
| // Last finished IPC order number.
|
| - uint32_t processed_order_num_;
|
| + uint32_t processed_order_num_ = 0;
|
|
|
| // Unprocessed order number expected to be processed under normal execution.
|
| - uint32_t unprocessed_order_num_;
|
| + uint32_t unprocessed_order_num_ = 0;
|
|
|
| // In situations where we are waiting on fence syncs that do not exist, we
|
| // validate by making sure the order number does not pass the order number
|
| @@ -137,24 +137,30 @@ class GPU_EXPORT SyncPointOrderData
|
| DISALLOW_COPY_AND_ASSIGN(SyncPointOrderData);
|
| };
|
|
|
| +// Internal state for sync point clients.
|
| class GPU_EXPORT SyncPointClientState
|
| : public base::RefCountedThreadSafe<SyncPointClientState> {
|
| public:
|
| - scoped_refptr<SyncPointOrderData> order_data() { return order_data_; }
|
| + explicit SyncPointClientState(scoped_refptr<SyncPointOrderData> order_data);
|
|
|
| - bool IsFenceSyncReleased(uint64_t release) {
|
| - return release <= fence_sync_release();
|
| - }
|
| + bool IsFenceSyncReleased(uint64_t release);
|
|
|
| - uint64_t fence_sync_release() {
|
| - base::AutoLock auto_lock(fence_sync_lock_);
|
| - return fence_sync_release_;
|
| - }
|
| + // Queues the callback to be called if the release is valid. If the release
|
| + // is invalid this function will return False and the callback will never
|
| + // be called.
|
| + bool WaitForRelease(uint64_t release,
|
| + uint32_t wait_order_num,
|
| + const base::Closure& callback);
|
| +
|
| + // Releases a fence sync and all fence syncs below.
|
| + void ReleaseFenceSync(uint64_t release);
|
| +
|
| + // Does not release the fence sync, but releases callbacks waiting on that
|
| + // fence sync.
|
| + void EnsureWaitReleased(uint64_t release, const base::Closure& callback);
|
|
|
| private:
|
| friend class base::RefCountedThreadSafe<SyncPointClientState>;
|
| - friend class SyncPointClient;
|
| - friend class SyncPointOrderData;
|
|
|
| struct ReleaseCallback {
|
| uint64_t release_count;
|
| @@ -173,29 +179,8 @@ class GPU_EXPORT SyncPointClientState
|
| std::greater<ReleaseCallback>>
|
| ReleaseCallbackQueue;
|
|
|
| - SyncPointClientState(scoped_refptr<SyncPointOrderData> order_data);
|
| ~SyncPointClientState();
|
|
|
| - // Queues the callback to be called if the release is valid. If the release
|
| - // is invalid this function will return False and the callback will never
|
| - // be called.
|
| - bool WaitForRelease(CommandBufferNamespace namespace_id,
|
| - CommandBufferId client_id,
|
| - uint32_t wait_order_num,
|
| - uint64_t release,
|
| - const base::Closure& callback);
|
| -
|
| - // Releases a fence sync and all fence syncs below.
|
| - void ReleaseFenceSync(uint64_t release);
|
| -
|
| - // Does not release the fence sync, but releases callbacks waiting on that
|
| - // fence sync.
|
| - void EnsureWaitReleased(uint64_t release, const base::Closure& callback);
|
| -
|
| - typedef base::Callback<void(CommandBufferNamespace, CommandBufferId)>
|
| - OnWaitCallback;
|
| - void SetOnWaitCallback(const OnWaitCallback& callback);
|
| -
|
| // Global order data where releases will originate from.
|
| scoped_refptr<SyncPointOrderData> order_data_;
|
|
|
| @@ -203,87 +188,47 @@ class GPU_EXPORT SyncPointClientState
|
| base::Lock fence_sync_lock_;
|
|
|
| // Current fence sync release that has been signaled.
|
| - uint64_t fence_sync_release_;
|
| + uint64_t fence_sync_release_ = 0;
|
|
|
| // In well defined fence sync operations, fence syncs are released in order
|
| // so simply having a priority queue for callbacks is enough.
|
| ReleaseCallbackQueue release_callback_queue_;
|
|
|
| - // Called when a release callback is queued.
|
| - OnWaitCallback on_wait_callback_;
|
| -
|
| DISALLOW_COPY_AND_ASSIGN(SyncPointClientState);
|
| };
|
|
|
| class GPU_EXPORT SyncPointClient {
|
| public:
|
| + SyncPointClient(SyncPointManager* sync_point_manager,
|
| + scoped_refptr<SyncPointOrderData> order_data,
|
| + CommandBufferNamespace namespace_id,
|
| + CommandBufferId command_buffer_id);
|
| ~SyncPointClient();
|
|
|
| - scoped_refptr<SyncPointClientState> client_state() { return client_state_; }
|
| -
|
| - // Wait for a release count to be reached on a SyncPointClientState. If this
|
| - // function returns false, that means the wait was invalid. Otherwise if it
|
| - // returns True it means the release was valid. In the case where the release
|
| - // is valid but has happened already, it will still return true. In all cases
|
| - // wait_complete_callback will be called eventually. The callback function
|
| - // may be called on another thread so it should be thread-safe. For
|
| - // convenience, another non-threadsafe version is defined below where you
|
| - // can supply a task runner.
|
| - bool Wait(SyncPointClientState* release_state,
|
| - uint64_t release_count,
|
| - const base::Closure& wait_complete_callback);
|
| -
|
| - bool WaitNonThreadSafe(SyncPointClientState* release_state,
|
| - uint64_t release_count,
|
| - scoped_refptr<base::SingleThreadTaskRunner> runner,
|
| - const base::Closure& wait_complete_callback);
|
| -
|
| - // Unordered waits are waits which do not occur within the global order number
|
| - // processing order (IE. Not between the corresponding
|
| - // SyncPointOrderData::BeginProcessingOrderNumber() and
|
| - // SyncPointOrderData::FinishProcessingOrderNumber() calls). Because fence
|
| - // sync releases must occur within a corresponding order number, these waits
|
| - // cannot deadlock because they can never depend on any fence sync releases.
|
| - // This is useful for IPC messages that may be processed out of order with
|
| - // respect to regular command buffer processing.
|
| - bool WaitOutOfOrder(SyncPointClientState* release_state,
|
| - uint64_t release_count,
|
| - const base::Closure& wait_complete_callback);
|
| + // This behaves similarly to SyncPointManager::Wait but uses the order data
|
| + // to guarantee no deadlocks with other clients.
|
| + bool Wait(const SyncToken& sync_token, const base::Closure& callback);
|
|
|
| - bool WaitOutOfOrderNonThreadSafe(
|
| - SyncPointClientState* release_state,
|
| - uint64_t release_count,
|
| - scoped_refptr<base::SingleThreadTaskRunner> runner,
|
| - const base::Closure& wait_complete_callback);
|
| + // Like Wait but runs the callback on the given task runner's thread.
|
| + bool WaitNonThreadSafe(
|
| + const SyncToken& sync_token,
|
| + scoped_refptr<base::SingleThreadTaskRunner> task_runner,
|
| + const base::Closure& callback);
|
|
|
| + // Release fence sync and run queued callbacks.
|
| void ReleaseFenceSync(uint64_t release);
|
|
|
| - // This callback is called with the namespace and id of the waiting client
|
| - // when a release callback is queued. The callback is called on the thread
|
| - // where the Wait... happens and synchronization is the responsibility of the
|
| - // caller.
|
| - typedef base::Callback<void(CommandBufferNamespace, CommandBufferId)>
|
| - OnWaitCallback;
|
| - void SetOnWaitCallback(const OnWaitCallback& callback);
|
| -
|
| private:
|
| - friend class SyncPointManager;
|
| -
|
| - SyncPointClient();
|
| - SyncPointClient(SyncPointManager* sync_point_manager,
|
| - scoped_refptr<SyncPointOrderData> order_data,
|
| - CommandBufferNamespace namespace_id,
|
| - CommandBufferId client_id);
|
| -
|
| // Sync point manager is guaranteed to exist in the lifetime of the client.
|
| - SyncPointManager* sync_point_manager_;
|
| + SyncPointManager* const sync_point_manager_;
|
| +
|
| + scoped_refptr<SyncPointOrderData> order_data_;
|
|
|
| - // Keep the state that is sharable across multiple threads.
|
| scoped_refptr<SyncPointClientState> client_state_;
|
|
|
| // Unique namespace/client id pair for this sync point client.
|
| const CommandBufferNamespace namespace_id_;
|
| - const CommandBufferId client_id_;
|
| + const CommandBufferId command_buffer_id_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(SyncPointClient);
|
| };
|
| @@ -292,42 +237,67 @@ class GPU_EXPORT SyncPointClient {
|
| // synchronization.
|
| class GPU_EXPORT SyncPointManager {
|
| public:
|
| - explicit SyncPointManager(bool allow_threaded_wait);
|
| + SyncPointManager();
|
| ~SyncPointManager();
|
|
|
| - // Creates/Destroy a sync point client which message processors should hold.
|
| - std::unique_ptr<SyncPointClient> CreateSyncPointClient(
|
| - scoped_refptr<SyncPointOrderData> order_data,
|
| - CommandBufferNamespace namespace_id,
|
| - CommandBufferId client_id);
|
| + // Returns true if the sync token has been released or if the command buffer
|
| + // does not exist.
|
| + bool IsSyncTokenReleased(const SyncToken& sync_token);
|
| +
|
| + // If the wait is valid (sync token hasn't been processed or command buffer
|
| + // does not exist), the callback is queued to run when the sync point is
|
| + // released. If the wait is invalid, the callback is NOT run. The callback
|
| + // runs on the thread the sync point is released. Clients should use
|
| + // SyncPointClient::Wait because that uses order data to prevent deadlocks.
|
| + bool Wait(const SyncToken& sync_token,
|
| + uint32_t wait_order_num,
|
| + const base::Closure& callback);
|
| +
|
| + // Like Wait but runs the callback on the given task runner's thread.
|
| + bool WaitNonThreadSafe(
|
| + const SyncToken& sync_token,
|
| + uint32_t wait_order_num,
|
| + scoped_refptr<base::SingleThreadTaskRunner> task_runner,
|
| + const base::Closure& callback);
|
|
|
| - // Creates a sync point client which cannot process order numbers but can only
|
| - // Wait out of order.
|
| - std::unique_ptr<SyncPointClient> CreateSyncPointClientWaiter();
|
| + // WaitOutOfOrder allows waiting for a sync token indefinitely, so it
|
| + // should be used with trusted sync tokens only.
|
| + bool WaitOutOfOrder(const SyncToken& trusted_sync_token,
|
| + const base::Closure& callback);
|
|
|
| - // Finds the state of an already created sync point client.
|
| - scoped_refptr<SyncPointClientState> GetSyncPointClientState(
|
| - CommandBufferNamespace namespace_id,
|
| - CommandBufferId client_id);
|
| + // Like WaitOutOfOrder but runs the callback on the given task runner's
|
| + // thread.
|
| + bool WaitOutOfOrderNonThreadSafe(
|
| + const SyncToken& trusted_sync_token,
|
| + scoped_refptr<base::SingleThreadTaskRunner> task_runner,
|
| + const base::Closure& callback);
|
|
|
| - private:
|
| - friend class SyncPointClient;
|
| - friend class SyncPointOrderData;
|
| + // Used by SyncPointClient.
|
| + void RegisterSyncPointClient(scoped_refptr<SyncPointClientState> client_state,
|
| + CommandBufferNamespace namespace_id,
|
| + CommandBufferId command_buffer_id);
|
|
|
| - using ClientMap = std::unordered_map<CommandBufferId,
|
| - SyncPointClient*,
|
| - CommandBufferId::Hasher>;
|
| + void DeregisterSyncPointClient(CommandBufferNamespace namespace_id,
|
| + CommandBufferId command_buffer_id);
|
|
|
| + // Used by SyncPointOrderData.
|
| uint32_t GenerateOrderNumber();
|
| - void DestroySyncPointClient(CommandBufferNamespace namespace_id,
|
| - CommandBufferId client_id);
|
| +
|
| + private:
|
| + using ClientStateMap = std::unordered_map<CommandBufferId,
|
| + scoped_refptr<SyncPointClientState>,
|
| + CommandBufferId::Hasher>;
|
| +
|
| + scoped_refptr<SyncPointClientState> GetSyncPointClientState(
|
| + CommandBufferNamespace namespace_id,
|
| + CommandBufferId command_buffer_id);
|
|
|
| // Order number is global for all clients.
|
| base::AtomicSequenceNumber global_order_num_;
|
|
|
| // Client map holds a map of clients id to client for each namespace.
|
| - base::Lock client_maps_lock_;
|
| - ClientMap client_maps_[NUM_COMMAND_BUFFER_NAMESPACES];
|
| + base::Lock client_state_maps_lock_;
|
| + ClientStateMap client_state_maps_[NUM_COMMAND_BUFFER_NAMESPACES];
|
|
|
| DISALLOW_COPY_AND_ASSIGN(SyncPointManager);
|
| };
|
|
|