OLD | NEW |
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 #ifndef GPU_COMMAND_BUFFER_SERVICE_SYNC_POINT_MANAGER_H_ | 5 #ifndef GPU_COMMAND_BUFFER_SERVICE_SYNC_POINT_MANAGER_H_ |
6 #define GPU_COMMAND_BUFFER_SERVICE_SYNC_POINT_MANAGER_H_ | 6 #define GPU_COMMAND_BUFFER_SERVICE_SYNC_POINT_MANAGER_H_ |
7 | 7 |
| 8 #include <functional> |
| 9 #include <queue> |
8 #include <vector> | 10 #include <vector> |
9 | 11 |
10 #include "base/atomic_sequence_num.h" | 12 #include "base/atomic_sequence_num.h" |
11 #include "base/callback.h" | 13 #include "base/callback.h" |
12 #include "base/containers/hash_tables.h" | 14 #include "base/containers/hash_tables.h" |
13 #include "base/logging.h" | 15 #include "base/logging.h" |
14 #include "base/memory/ref_counted.h" | 16 #include "base/memory/ref_counted.h" |
15 #include "base/memory/scoped_ptr.h" | 17 #include "base/memory/scoped_ptr.h" |
16 #include "base/synchronization/condition_variable.h" | 18 #include "base/synchronization/condition_variable.h" |
17 #include "base/synchronization/lock.h" | 19 #include "base/synchronization/lock.h" |
18 #include "base/threading/thread_checker.h" | 20 #include "base/threading/thread_checker.h" |
19 #include "gpu/command_buffer/common/constants.h" | 21 #include "gpu/command_buffer/common/constants.h" |
20 #include "gpu/gpu_export.h" | 22 #include "gpu/gpu_export.h" |
21 | 23 |
| 24 namespace base { |
| 25 class SingleThreadTaskRunner; |
| 26 } // namespace base |
| 27 |
22 namespace gpu { | 28 namespace gpu { |
23 | 29 |
24 class SyncPointClient; | 30 class SyncPointClient; |
| 31 class SyncPointClientState; |
25 class SyncPointManager; | 32 class SyncPointManager; |
26 | 33 |
27 class GPU_EXPORT SyncPointClientState | 34 class GPU_EXPORT SyncPointOrderData |
28 : public base::RefCountedThreadSafe<SyncPointClientState> { | 35 : public base::RefCountedThreadSafe<SyncPointOrderData> { |
29 public: | 36 public: |
30 static scoped_refptr<SyncPointClientState> Create(); | 37 static scoped_refptr<SyncPointOrderData> Create(); |
| 38 void Destroy(); |
| 39 |
31 uint32_t GenerateUnprocessedOrderNumber(SyncPointManager* sync_point_manager); | 40 uint32_t GenerateUnprocessedOrderNumber(SyncPointManager* sync_point_manager); |
32 | 41 void BeginProcessingOrderNumber(uint32_t order_num); |
33 void BeginProcessingOrderNumber(uint32_t order_num) { | 42 void FinishProcessingOrderNumber(uint32_t order_num); |
34 DCHECK(processing_thread_checker_.CalledOnValidThread()); | |
35 DCHECK_GE(order_num, current_order_num_); | |
36 current_order_num_ = order_num; | |
37 } | |
38 | |
39 void FinishProcessingOrderNumber(uint32_t order_num) { | |
40 DCHECK(processing_thread_checker_.CalledOnValidThread()); | |
41 DCHECK_EQ(current_order_num_, order_num); | |
42 DCHECK_GT(order_num, processed_order_num()); | |
43 base::subtle::Release_Store(&processed_order_num_, order_num); | |
44 } | |
45 | 43 |
46 uint32_t processed_order_num() const { | 44 uint32_t processed_order_num() const { |
47 return base::subtle::Acquire_Load(&processed_order_num_); | 45 base::AutoLock auto_lock(lock_); |
| 46 return processed_order_num_; |
48 } | 47 } |
49 | 48 |
50 uint32_t unprocessed_order_num() const { | 49 uint32_t unprocessed_order_num() const { |
51 return base::subtle::Acquire_Load(&unprocessed_order_num_); | 50 base::AutoLock auto_lock(lock_); |
| 51 return unprocessed_order_num_; |
52 } | 52 } |
53 | 53 |
54 uint32_t current_order_num() const { | 54 uint32_t current_order_num() const { |
55 DCHECK(processing_thread_checker_.CalledOnValidThread()); | 55 DCHECK(processing_thread_checker_.CalledOnValidThread()); |
56 return current_order_num_; | 56 return current_order_num_; |
57 } | 57 } |
58 | 58 |
59 protected: | 59 private: |
60 friend class base::RefCountedThreadSafe<SyncPointClientState>; | 60 friend class base::RefCountedThreadSafe<SyncPointOrderData>; |
61 friend class SyncPointClient; | 61 friend class SyncPointClientState; |
62 | 62 |
63 SyncPointClientState(); | 63 struct OrderFence { |
64 virtual ~SyncPointClientState(); | 64 uint32_t order_num; |
| 65 uint64_t fence_release; |
| 66 scoped_refptr<SyncPointClientState> client_state; |
65 | 67 |
66 // Last finished IPC order number. | 68 OrderFence(uint32_t order, |
67 base::subtle::Atomic32 processed_order_num_; | 69 uint64_t release, |
| 70 scoped_refptr<SyncPointClientState> state); |
| 71 ~OrderFence(); |
68 | 72 |
69 // Unprocessed order number expected to be processed under normal execution. | 73 bool operator>(const OrderFence& rhs) const { |
70 base::subtle::Atomic32 unprocessed_order_num_; | 74 return (order_num > rhs.order_num) || |
| 75 ((order_num == rhs.order_num) && |
| 76 (fence_release > rhs.fence_release)); |
| 77 } |
| 78 }; |
| 79 typedef std::priority_queue<OrderFence, |
| 80 std::vector<OrderFence>, |
| 81 std::greater<OrderFence>> OrderFenceQueue; |
| 82 |
| 83 SyncPointOrderData(); |
| 84 ~SyncPointOrderData(); |
| 85 |
| 86 bool ValidateReleaseOrderNumber( |
| 87 scoped_refptr<SyncPointClientState> client_state, |
| 88 uint32_t wait_order_num, |
| 89 uint64_t fence_release); |
71 | 90 |
72 // Non thread-safe functions need to be called from a single thread. | 91 // Non thread-safe functions need to be called from a single thread. |
73 base::ThreadChecker processing_thread_checker_; | 92 base::ThreadChecker processing_thread_checker_; |
74 | 93 |
75 // Current IPC order number being processed (only used on processing thread). | 94 // Current IPC order number being processed (only used on processing thread). |
76 uint32_t current_order_num_; | 95 uint32_t current_order_num_; |
77 | 96 |
| 97 // This lock protects destroyed_, processed_order_num_, |
| 98 // unprocessed_order_num_, and order_fence_queue_. All order numbers (n) in |
| 99 // order_fence_queue_ must follow the invariant: |
| 100 // processed_order_num_ < n <= unprocessed_order_num_. |
| 101 mutable base::Lock lock_; |
| 102 |
| 103 bool destroyed_; |
| 104 |
| 105 // Last finished IPC order number. |
| 106 uint32_t processed_order_num_; |
| 107 |
| 108 // Unprocessed order number expected to be processed under normal execution. |
| 109 uint32_t unprocessed_order_num_; |
| 110 |
| 111 // In situations where we are waiting on fence syncs that do not exist, we |
| 112 // validate by making sure the order number does not pass the order number |
| 113 // which the wait command was issued. If the order number reaches the |
| 114 // wait command's, we should automatically release up to the expected |
| 115 // release count. Note that this also releases other lower release counts, |
| 116 // so a single misbehaved fence sync is enough to invalidate/signal all |
| 117 // previous fence syncs. |
| 118 OrderFenceQueue order_fence_queue_; |
| 119 |
| 120 DISALLOW_COPY_AND_ASSIGN(SyncPointOrderData); |
| 121 }; |
| 122 |
| 123 class GPU_EXPORT SyncPointClientState |
| 124 : public base::RefCountedThreadSafe<SyncPointClientState> { |
| 125 public: |
| 126 scoped_refptr<SyncPointOrderData> order_data() { return order_data_; } |
| 127 |
| 128 bool IsFenceSyncReleased(uint64_t release) { |
| 129 return release <= fence_sync_release(); |
| 130 } |
| 131 |
| 132 uint64_t fence_sync_release() { |
| 133 base::AutoLock auto_lock(fence_sync_lock_); |
| 134 return fence_sync_release_; |
| 135 } |
| 136 |
| 137 private: |
| 138 friend class base::RefCountedThreadSafe<SyncPointClientState>; |
| 139 friend class SyncPointClient; |
| 140 friend class SyncPointOrderData; |
| 141 |
| 142 struct ReleaseCallback { |
| 143 uint64_t release_count; |
| 144 base::Closure callback_closure; |
| 145 |
| 146 ReleaseCallback(uint64_t release, const base::Closure& callback); |
| 147 ~ReleaseCallback(); |
| 148 |
| 149 bool operator>(const ReleaseCallback& rhs) const { |
| 150 return release_count > rhs.release_count; |
| 151 } |
| 152 }; |
| 153 typedef std::priority_queue<ReleaseCallback, |
| 154 std::vector<ReleaseCallback>, |
| 155 std::greater<ReleaseCallback>> |
| 156 ReleaseCallbackQueue; |
| 157 |
| 158 SyncPointClientState(scoped_refptr<SyncPointOrderData> order_data); |
| 159 ~SyncPointClientState(); |
| 160 |
| 161 // Queues the callback to be called if the release is valid. If the release |
| 162 // is invalid this function will return False and the callback will never |
| 163 // be called. |
| 164 bool WaitForRelease(uint32_t wait_order_num, |
| 165 uint64_t release, |
| 166 const base::Closure& callback); |
| 167 |
| 168 void ReleaseFenceSync(uint64_t release); |
| 169 void EnsureReleased(uint64_t release); |
| 170 void ReleaseFenceSyncLocked(uint64_t release, |
| 171 std::vector<base::Closure>* callback_list); |
| 172 |
| 173 // Global order data where releases will originate from. |
| 174 scoped_refptr<SyncPointOrderData> order_data_; |
| 175 |
| 176 // Protects fence_sync_release_, fence_callback_queue_. |
| 177 base::Lock fence_sync_lock_; |
| 178 |
| 179 // Current fence sync release that has been signaled. |
| 180 uint64_t fence_sync_release_; |
| 181 |
| 182 // In well defined fence sync operations, fence syncs are released in order |
| 183 // so simply having a priority queue for callbacks is enough. |
| 184 ReleaseCallbackQueue release_callback_queue_; |
| 185 |
78 DISALLOW_COPY_AND_ASSIGN(SyncPointClientState); | 186 DISALLOW_COPY_AND_ASSIGN(SyncPointClientState); |
79 }; | 187 }; |
80 | 188 |
81 class GPU_EXPORT SyncPointClient { | 189 class GPU_EXPORT SyncPointClient { |
82 public: | 190 public: |
83 ~SyncPointClient(); | 191 ~SyncPointClient(); |
84 | 192 |
85 scoped_refptr<SyncPointClientState> client_state() { return client_state_; } | 193 scoped_refptr<SyncPointClientState> client_state() { return client_state_; } |
86 | 194 |
| 195 // Wait for a release count to be reached on a SyncPointClientState. If this |
| 196 // function returns false, that means the wait was invalid. Otherwise if it |
| 197 // returns True it means the release was valid. In the case where the release |
| 198 // is valid but has happened already, it will still return true. In all cases |
| 199 // wait_complete_callback will be called eventually. The callback function |
| 200 // may be called on another thread so it should be thread-safe. For |
| 201 // convenience, another non-threadsafe version is defined below where you |
| 202 // can supply a task runner. |
| 203 bool Wait(SyncPointClientState* release_state, |
| 204 uint64_t release_count, |
| 205 const base::Closure& wait_complete_callback); |
| 206 |
| 207 bool WaitNonThreadSafe(SyncPointClientState* release_state, |
| 208 uint64_t release_count, |
| 209 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 210 const base::Closure& wait_complete_callback); |
| 211 |
| 212 void ReleaseFenceSync(uint64_t release); |
| 213 |
87 private: | 214 private: |
88 friend class SyncPointManager; | 215 friend class SyncPointManager; |
89 | 216 |
90 SyncPointClient(SyncPointManager* sync_point_manager, | 217 SyncPointClient(SyncPointManager* sync_point_manager, |
91 scoped_refptr<SyncPointClientState> state, | 218 scoped_refptr<SyncPointOrderData> order_data, |
92 CommandBufferNamespace namespace_id, uint64_t client_id); | 219 CommandBufferNamespace namespace_id, |
| 220 uint64_t client_id); |
93 | 221 |
94 // Sync point manager is guaranteed to exist in the lifetime of the client. | 222 // Sync point manager is guaranteed to exist in the lifetime of the client. |
95 SyncPointManager* sync_point_manager_; | 223 SyncPointManager* sync_point_manager_; |
96 | 224 |
97 // Keep the state that is sharable across multiple threads. | 225 // Keep the state that is sharable across multiple threads. |
98 scoped_refptr<SyncPointClientState> client_state_; | 226 scoped_refptr<SyncPointClientState> client_state_; |
99 | 227 |
100 // Unique namespace/client id pair for this sync point client. | 228 // Unique namespace/client id pair for this sync point client. |
101 CommandBufferNamespace namespace_id_; | 229 const CommandBufferNamespace namespace_id_; |
102 uint64_t client_id_; | 230 const uint64_t client_id_; |
103 | 231 |
104 DISALLOW_COPY_AND_ASSIGN(SyncPointClient); | 232 DISALLOW_COPY_AND_ASSIGN(SyncPointClient); |
105 }; | 233 }; |
106 | 234 |
107 // This class manages the sync points, which allow cross-channel | 235 // This class manages the sync points, which allow cross-channel |
108 // synchronization. | 236 // synchronization. |
109 class GPU_EXPORT SyncPointManager { | 237 class GPU_EXPORT SyncPointManager { |
110 public: | 238 public: |
111 explicit SyncPointManager(bool allow_threaded_wait); | 239 explicit SyncPointManager(bool allow_threaded_wait); |
112 ~SyncPointManager(); | 240 ~SyncPointManager(); |
113 | 241 |
114 // Creates/Destroy a sync point client which message processors should hold. | 242 // Creates/Destroy a sync point client which message processors should hold. |
115 scoped_ptr<SyncPointClient> CreateSyncPointClient( | 243 scoped_ptr<SyncPointClient> CreateSyncPointClient( |
116 scoped_refptr<SyncPointClientState> client_state, | 244 scoped_refptr<SyncPointOrderData> order_data, |
117 CommandBufferNamespace namespace_id, uint64_t client_id); | 245 CommandBufferNamespace namespace_id, |
| 246 uint64_t client_id); |
118 | 247 |
119 // Finds the state of an already created sync point client. | 248 // Finds the state of an already created sync point client. |
120 scoped_refptr<SyncPointClientState> GetSyncPointClientState( | 249 scoped_refptr<SyncPointClientState> GetSyncPointClientState( |
121 CommandBufferNamespace namespace_id, uint64_t client_id); | 250 CommandBufferNamespace namespace_id, uint64_t client_id); |
122 | 251 |
123 // Generates a sync point, returning its ID. This can me called on any thread. | 252 // Generates a sync point, returning its ID. This can me called on any thread. |
124 // IDs start at a random number. Never return 0. | 253 // IDs start at a random number. Never return 0. |
125 uint32 GenerateSyncPoint(); | 254 uint32 GenerateSyncPoint(); |
126 | 255 |
127 // Retires a sync point. This will call all the registered callbacks for this | 256 // Retires a sync point. This will call all the registered callbacks for this |
128 // sync point. This can only be called on the main thread. | 257 // sync point. This can only be called on the main thread. |
129 void RetireSyncPoint(uint32 sync_point); | 258 void RetireSyncPoint(uint32 sync_point); |
130 | 259 |
131 // Adds a callback to the sync point. The callback will be called when the | 260 // Adds a callback to the sync point. The callback will be called when the |
132 // sync point is retired, or immediately (from within that function) if the | 261 // sync point is retired, or immediately (from within that function) if the |
133 // sync point was already retired (or not created yet). This can only be | 262 // sync point was already retired (or not created yet). This can only be |
134 // called on the main thread. | 263 // called on the main thread. |
135 void AddSyncPointCallback(uint32 sync_point, const base::Closure& callback); | 264 void AddSyncPointCallback(uint32 sync_point, const base::Closure& callback); |
136 | 265 |
137 bool IsSyncPointRetired(uint32 sync_point); | 266 bool IsSyncPointRetired(uint32 sync_point); |
138 | 267 |
139 // Block and wait until a sync point is signaled. This is only useful when | 268 // Block and wait until a sync point is signaled. This is only useful when |
140 // the sync point is signaled on another thread. | 269 // the sync point is signaled on another thread. |
141 void WaitSyncPoint(uint32 sync_point); | 270 void WaitSyncPoint(uint32 sync_point); |
142 | 271 |
143 private: | 272 private: |
144 friend class SyncPointClient; | 273 friend class SyncPointClient; |
145 friend class SyncPointClientState; | 274 friend class SyncPointOrderData; |
146 | 275 |
147 typedef std::vector<base::Closure> ClosureList; | 276 typedef std::vector<base::Closure> ClosureList; |
148 typedef base::hash_map<uint32, ClosureList> SyncPointMap; | 277 typedef base::hash_map<uint32, ClosureList> SyncPointMap; |
149 typedef base::hash_map<uint64_t, SyncPointClient*> ClientMap; | 278 typedef base::hash_map<uint64_t, SyncPointClient*> ClientMap; |
150 | 279 |
151 bool IsSyncPointRetiredLocked(uint32 sync_point); | 280 bool IsSyncPointRetiredLocked(uint32 sync_point); |
152 uint32_t GenerateOrderNumber(); | 281 uint32_t GenerateOrderNumber(); |
153 void DestroySyncPointClient(CommandBufferNamespace namespace_id, | 282 void DestroySyncPointClient(CommandBufferNamespace namespace_id, |
154 uint64_t client_id); | 283 uint64_t client_id); |
155 | 284 |
(...skipping 12 matching lines...) Expand all Loading... |
168 SyncPointMap sync_point_map_; | 297 SyncPointMap sync_point_map_; |
169 uint32 next_sync_point_; | 298 uint32 next_sync_point_; |
170 base::ConditionVariable retire_cond_var_; | 299 base::ConditionVariable retire_cond_var_; |
171 | 300 |
172 DISALLOW_COPY_AND_ASSIGN(SyncPointManager); | 301 DISALLOW_COPY_AND_ASSIGN(SyncPointManager); |
173 }; | 302 }; |
174 | 303 |
175 } // namespace gpu | 304 } // namespace gpu |
176 | 305 |
177 #endif // GPU_COMMAND_BUFFER_SERVICE_SYNC_POINT_MANAGER_H_ | 306 #endif // GPU_COMMAND_BUFFER_SERVICE_SYNC_POINT_MANAGER_H_ |
OLD | NEW |