Chromium Code Reviews| 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 3f11e05dabbe407ea9c27e018c759701e3fedbb3..26930602e3df57a8ca9489c4de8ffa8f3bf30934 100644 |
| --- a/gpu/command_buffer/service/sync_point_manager.h |
| +++ b/gpu/command_buffer/service/sync_point_manager.h |
| @@ -5,6 +5,8 @@ |
| #ifndef GPU_COMMAND_BUFFER_SERVICE_SYNC_POINT_MANAGER_H_ |
| #define GPU_COMMAND_BUFFER_SERVICE_SYNC_POINT_MANAGER_H_ |
| +#include <functional> |
| +#include <queue> |
| #include <vector> |
| #include "base/atomic_sequence_num.h" |
| @@ -19,29 +21,25 @@ |
| #include "gpu/command_buffer/common/constants.h" |
| #include "gpu/gpu_export.h" |
| +namespace base { |
| +class SingleThreadTaskRunner; |
| +} // namespace base |
| + |
| namespace gpu { |
| class SyncPointClient; |
| +class SyncPointClientState; |
| class SyncPointManager; |
| -class GPU_EXPORT SyncPointClientState |
| - : public base::RefCountedThreadSafe<SyncPointClientState> { |
| +class GPU_EXPORT SyncPointOrderData |
| + : public base::RefCountedThreadSafe<SyncPointOrderData> { |
| public: |
| - static scoped_refptr<SyncPointClientState> Create(); |
| - uint32_t GenerateUnprocessedOrderNumber(SyncPointManager* sync_point_manager); |
| - |
| - void BeginProcessingOrderNumber(uint32_t order_num) { |
| - DCHECK(processing_thread_checker_.CalledOnValidThread()); |
| - DCHECK_GE(order_num, current_order_num_); |
| - current_order_num_ = order_num; |
| - } |
| + static scoped_refptr<SyncPointOrderData> Create(); |
| + void Destroy(); |
| - void FinishProcessingOrderNumber(uint32_t order_num) { |
| - DCHECK(processing_thread_checker_.CalledOnValidThread()); |
| - DCHECK_EQ(current_order_num_, order_num); |
| - DCHECK_GT(order_num, processed_order_num()); |
| - base::subtle::Release_Store(&processed_order_num_, order_num); |
| - } |
| + uint32_t GenerateUnprocessedOrderNumber(SyncPointManager* sync_point_manager); |
| + void BeginProcessingOrderNumber(uint32_t order_num); |
| + void FinishProcessingOrderNumber(uint32_t order_num); |
| uint32_t processed_order_num() const { |
| return base::subtle::Acquire_Load(&processed_order_num_); |
| @@ -57,11 +55,33 @@ class GPU_EXPORT SyncPointClientState |
| } |
| protected: |
| - friend class base::RefCountedThreadSafe<SyncPointClientState>; |
| - friend class SyncPointClient; |
| + friend class base::RefCountedThreadSafe<SyncPointOrderData>; |
| + friend class SyncPointClientState; |
| - SyncPointClientState(); |
| - virtual ~SyncPointClientState(); |
| + struct OrderFence { |
| + uint32_t order_num; |
| + uint64_t fence_release; |
| + scoped_refptr<SyncPointClientState> client_state; |
| + |
| + OrderFence(uint32_t order, uint64_t release, |
| + scoped_refptr<SyncPointClientState> state); |
| + ~OrderFence(); |
| + |
| + bool operator>(const OrderFence& rhs) const { |
| + return (order_num > rhs.order_num) || |
| + ((order_num == rhs.order_num) && |
| + (fence_release > rhs.fence_release)); |
| + } |
| + }; |
| + typedef std::priority_queue<OrderFence, |
| + std::vector<OrderFence>, |
| + std::greater<OrderFence>> OrderFenceQueue; |
| + |
| + SyncPointOrderData(); |
| + virtual ~SyncPointOrderData(); |
|
piman
2015/09/30 22:50:23
This doesn't need to be virtual, because nothing d
David Yen
2015/09/30 23:55:18
Done.
|
| + |
| + void AddOrderFenceGuard(uint32_t order_num, uint64_t fence_release, |
| + scoped_refptr<SyncPointClientState> client_state); |
| // Last finished IPC order number. |
| base::subtle::Atomic32 processed_order_num_; |
| @@ -75,6 +95,79 @@ class GPU_EXPORT SyncPointClientState |
| // Current IPC order number being processed (only used on processing thread). |
| uint32_t current_order_num_; |
| + // 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 |
| + // which the wait command was issued. If the order number reaches the |
| + // wait command's, we should automatically release up to the expected |
| + // release count. Note that this also releases other lower release counts, |
| + // so a single misbehaved fence sync is enough to invalidate/signal all |
| + // previous fence syncs. |
| + base::Lock order_fence_queue_lock_; |
| + OrderFenceQueue order_fence_queue_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(SyncPointOrderData); |
| +}; |
| + |
| +class GPU_EXPORT SyncPointClientState |
| + : public base::RefCountedThreadSafe<SyncPointClientState> { |
| + public: |
| + scoped_refptr<SyncPointOrderData> order_data() { return order_data_; } |
| + |
| + bool IsFenceSyncReleased(uint64_t release) { |
| + return release <= fence_sync_release(); |
| + } |
| + |
| + uint64_t fence_sync_release() { |
| + base::AutoLock auto_lock(fence_sync_lock_); |
| + return fence_sync_release_; |
| + } |
| + |
| + protected: |
| + friend class base::RefCountedThreadSafe<SyncPointClientState>; |
| + friend class SyncPointClient; |
| + friend class SyncPointOrderData; |
| + |
| + struct ReleaseCallback { |
| + uint64_t release_count; |
| + base::Closure callback_closure; |
| + |
| + ReleaseCallback(uint64_t release, const base::Closure& callback); |
| + ~ReleaseCallback(); |
| + |
| + bool operator>(const ReleaseCallback& rhs) const { |
| + return release_count > rhs.release_count; |
| + } |
| + }; |
| + typedef std::priority_queue< |
| + ReleaseCallback, |
| + std::vector<ReleaseCallback>, |
| + std::greater<ReleaseCallback>> ReleaseCallbackQueue; |
| + |
| + SyncPointClientState(scoped_refptr<SyncPointOrderData> order_data); |
| + virtual ~SyncPointClientState(); |
|
piman
2015/09/30 22:50:23
same here, no need to be virtual.
David Yen
2015/09/30 23:55:18
Done.
|
| + |
| + bool WaitForRelease(uint32_t wait_order_num, |
| + uint64_t release, |
| + const base::Closure& callback); |
| + |
| + void ReleaseFenceSync(uint64_t release); |
| + void EnsureReleased(uint64_t release); |
| + void ReleaseFenceSyncLocked(uint64_t release, |
| + std::vector<base::Closure>* callback_list); |
| + |
| + // Global order data where releases will originate from. |
| + scoped_refptr<SyncPointOrderData> order_data_; |
| + |
| + // Protects fence_sync_release_, fence_callback_queue_. |
| + base::Lock fence_sync_lock_; |
| + |
| + // Current fence sync release that has been signaled. |
| + uint64_t fence_sync_release_; |
| + |
| + // 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_; |
| + |
| DISALLOW_COPY_AND_ASSIGN(SyncPointClientState); |
| }; |
| @@ -84,11 +177,29 @@ class GPU_EXPORT 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 wait_complete_callback will be called eventually. |
| + // In the case where the release happened already, it will call the callback |
| + // immediately before returning. The callback function may be called on |
| + // 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(scoped_refptr<SyncPointClientState> release_state, |
| + uint64_t release_count, |
| + const base::Closure& wait_complete_callback); |
| + |
| + bool WaitNonThreadSafe(scoped_refptr<SyncPointClientState> release_state, |
| + uint64_t release_count, |
| + scoped_refptr<base::SingleThreadTaskRunner> runner, |
| + const base::Closure& wait_complete_callback); |
| + |
| + void ReleaseFenceSync(uint64_t release); |
| + |
| private: |
| friend class SyncPointManager; |
| SyncPointClient(SyncPointManager* sync_point_manager, |
| - scoped_refptr<SyncPointClientState> state, |
| + scoped_refptr<SyncPointOrderData> order_data, |
| CommandBufferNamespace namespace_id, uint64_t client_id); |
| // Sync point manager is guaranteed to exist in the lifetime of the client. |
| @@ -98,8 +209,8 @@ class GPU_EXPORT SyncPointClient { |
| scoped_refptr<SyncPointClientState> client_state_; |
| // Unique namespace/client id pair for this sync point client. |
| - CommandBufferNamespace namespace_id_; |
| - uint64_t client_id_; |
| + const CommandBufferNamespace namespace_id_; |
| + const uint64_t client_id_; |
| DISALLOW_COPY_AND_ASSIGN(SyncPointClient); |
| }; |
| @@ -113,7 +224,7 @@ class GPU_EXPORT SyncPointManager { |
| // Creates/Destroy a sync point client which message processors should hold. |
| scoped_ptr<SyncPointClient> CreateSyncPointClient( |
| - scoped_refptr<SyncPointClientState> client_state, |
| + scoped_refptr<SyncPointOrderData> order_data, |
| CommandBufferNamespace namespace_id, uint64_t client_id); |
| // Finds the state of an already created sync point client. |
| @@ -142,7 +253,7 @@ class GPU_EXPORT SyncPointManager { |
| private: |
| friend class SyncPointClient; |
| - friend class SyncPointClientState; |
| + friend class SyncPointOrderData; |
| typedef std::vector<base::Closure> ClosureList; |
| typedef base::hash_map<uint32, ClosureList> SyncPointMap; |