Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(12)

Side by Side Diff: gpu/command_buffer/service/sync_point_manager.cc

Issue 1331843005: Implemented new fence syncs which replaces the old sync points. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed memory leak Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 #include "gpu/command_buffer/service/sync_point_manager.h" 5 #include "gpu/command_buffer/service/sync_point_manager.h"
6 6
7 #include <climits> 7 #include <climits>
8 8
9 #include "base/bind.h"
10 #include "base/containers/hash_tables.h"
11 #include "base/location.h"
9 #include "base/logging.h" 12 #include "base/logging.h"
10 #include "base/rand_util.h" 13 #include "base/rand_util.h"
11 #include "base/sequence_checker.h" 14 #include "base/sequence_checker.h"
15 #include "base/single_thread_task_runner.h"
12 16
13 namespace gpu { 17 namespace gpu {
14 18
15 static const int kMaxSyncBase = INT_MAX; 19 static const int kMaxSyncBase = INT_MAX;
16 20
17 scoped_refptr<SyncPointClientState> SyncPointClientState::Create() { 21 namespace {
18 return new SyncPointClientState; 22
19 } 23 void RunOnThread(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
20 24 const base::Closure& callback) {
21 uint32_t SyncPointClientState::GenerateUnprocessedOrderNumber( 25 if (task_runner->BelongsToCurrentThread()) {
26 callback.Run();
27 } else {
28 task_runner->PostTask(FROM_HERE, callback);
29 }
30 }
31
32 } // namespace
33
34 scoped_refptr<SyncPointOrderData> SyncPointOrderData::Create() {
35 return new SyncPointOrderData;
36 }
37
38 void SyncPointOrderData::Destroy() {
39 base::AutoLock auto_lock(order_fence_queue_lock_);
40 while (!order_fence_queue_.empty()) {
41 order_fence_queue_.pop();
42 }
43 }
44
45 uint32_t SyncPointOrderData::GenerateUnprocessedOrderNumber(
22 SyncPointManager* sync_point_manager) { 46 SyncPointManager* sync_point_manager) {
23 const uint32_t order_num = sync_point_manager->GenerateOrderNumber(); 47 const uint32_t order_num = sync_point_manager->GenerateOrderNumber();
24 base::subtle::Release_Store(&unprocessed_order_num_, order_num); 48 base::subtle::Release_Store(&unprocessed_order_num_, order_num);
25 return order_num; 49 return order_num;
26 } 50 }
27 51
28 SyncPointClientState::SyncPointClientState() 52 void SyncPointOrderData::BeginProcessingOrderNumber(uint32_t order_num) {
53 DCHECK(processing_thread_checker_.CalledOnValidThread());
54 DCHECK_GE(order_num, current_order_num_);
55 current_order_num_ = order_num;
56 }
57
58 void SyncPointOrderData::FinishProcessingOrderNumber(uint32_t order_num) {
59 DCHECK(processing_thread_checker_.CalledOnValidThread());
60 DCHECK_EQ(current_order_num_, order_num);
61 DCHECK_GT(order_num, processed_order_num());
62
63 // Catch invalid waits which were waiting on fence syncs that do not exist.
64 // Release without the lock to avoid possible deadlocks.
65 std::vector<OrderFence> ensure_releases;
66 {
67 base::AutoLock auto_lock(order_fence_queue_lock_);
68 while (!order_fence_queue_.empty()) {
69 const OrderFence& order_fence = order_fence_queue_.top();
70 if (order_fence_queue_.top().order_num <= order_num) {
71 ensure_releases.push_back(order_fence);
72 order_fence_queue_.pop();
73 continue;
74 }
75 break;
76 }
77 }
78 for (OrderFence& order_fence : ensure_releases) {
79 order_fence.client_state->EnsureReleased(order_fence.fence_release);
80 }
81
82 base::subtle::Release_Store(&processed_order_num_, order_num);
piman 2015/09/30 22:50:23 This should happen before we do the EnsureReleased
David Yen 2015/09/30 23:55:18 That is true, in that case even the release counts
83 }
84
85 SyncPointOrderData::OrderFence::OrderFence(
86 uint32_t order, uint64_t release, scoped_refptr<SyncPointClientState> state)
87 : order_num(order),
88 fence_release(release),
89 client_state(state) {
90 }
91
92 SyncPointOrderData::OrderFence::~OrderFence() {
93 }
94
95 SyncPointOrderData::SyncPointOrderData()
29 : processed_order_num_(0), 96 : processed_order_num_(0),
30 unprocessed_order_num_(0), 97 unprocessed_order_num_(0),
31 current_order_num_(0) { 98 current_order_num_(0) {
32 } 99 }
33 100
101 SyncPointOrderData::~SyncPointOrderData() {
102 }
103
104 void SyncPointOrderData::AddOrderFenceGuard(
105 uint32_t order_num, uint64_t fence_release,
106 scoped_refptr<SyncPointClientState> client_state) {
107 base::AutoLock auto_lock(order_fence_queue_lock_);
108 order_fence_queue_.push(OrderFence(order_num, fence_release, client_state));
109 }
110
111 SyncPointClientState::ReleaseCallback::ReleaseCallback(
112 uint64_t release, const base::Closure& callback)
113 : release_count(release),
114 callback_closure(callback) {
115 }
116
117 SyncPointClientState::ReleaseCallback::~ReleaseCallback() {
118 }
119
120 SyncPointClientState::SyncPointClientState(
121 scoped_refptr<SyncPointOrderData> order_data)
122 : order_data_(order_data),
123 fence_sync_release_(0) {
124 }
125
34 SyncPointClientState::~SyncPointClientState() { 126 SyncPointClientState::~SyncPointClientState() {
35 } 127 }
36 128
129 bool SyncPointClientState::WaitForRelease(uint32_t wait_order_num,
130 uint64_t release,
131 const base::Closure& callback) {
132 // Lock must be held the whole time while we validate otherwise it could be
133 // released while we are checking.
134 {
135 base::AutoLock auto_lock(fence_sync_lock_);
136 if (release > fence_sync_release_) {
137 const uint32_t processed_num = order_data_->processed_order_num();
138 const uint32_t unprocessed_num = order_data_->unprocessed_order_num();
139
140 // Release should have a possible unprocessed order number lower
141 // than the wait order number.
142 if ((processed_num + 1) >= wait_order_num)
piman 2015/09/30 22:50:23 I think this should be processed_num >= wait_order
David Yen 2015/09/30 23:55:18 This is a bit tricky and I only found it after wri
piman 2015/10/01 01:00:23 Ok, I think I convinced myself of why, but I think
David Yen 2015/10/01 17:15:51 Ah, that is a tricky case. I think we actually did
143 return false;
144
145 // Release should have more unprocessed numbers if we are waiting.
146 if (unprocessed_num <= processed_num)
147 return false;
148
149 // Add the callback which will be called upon release.
150 release_callback_queue_.push(ReleaseCallback(release, callback));
151
152 // Validate by ensuring fence is released by the expected order number.
153 const uint32_t expected_order_num = std::min(unprocessed_num,
154 wait_order_num);
155 order_data_->AddOrderFenceGuard(expected_order_num, release, this);
156 return true;
157 }
158 }
159
160 // Already released, run the callback now.
161 callback.Run();
162 return true;
163 }
164
165 void SyncPointClientState::ReleaseFenceSync(uint64_t release) {
166 // Call callbacks without the lock to avoid possible deadlocks.
167 std::vector<base::Closure> callback_list;
168 {
169 base::AutoLock auto_lock(fence_sync_lock_);
170 ReleaseFenceSyncLocked(release, &callback_list);
171 }
172
173 for (const base::Closure& closure : callback_list) {
174 closure.Run();
175 }
176 }
177
178 void SyncPointClientState::EnsureReleased(uint64_t release) {
179 // Call callbacks without the lock to avoid possible deadlocks.
180 std::vector<base::Closure> callback_list;
181 {
182 base::AutoLock auto_lock(fence_sync_lock_);
183 if (release <= fence_sync_release_)
184 return;
185
186 ReleaseFenceSyncLocked(release, &callback_list);
187 }
188
189 for (const base::Closure& closure : callback_list) {
190 closure.Run();
191 }
192 }
193
194 void SyncPointClientState::ReleaseFenceSyncLocked(
195 uint64_t release, std::vector<base::Closure>* callback_list) {
196 fence_sync_lock_.AssertAcquired();
197 DCHECK_GT(release, fence_sync_release_);
198
199 fence_sync_release_ = release;
200 while (!release_callback_queue_.empty() &&
201 release_callback_queue_.top().release_count <= release) {
202 callback_list->push_back(release_callback_queue_.top().callback_closure);
203 release_callback_queue_.pop();
204 }
205 }
206
37 SyncPointClient::~SyncPointClient() { 207 SyncPointClient::~SyncPointClient() {
208 // Release all fences on destruction.
209 ReleaseFenceSync(UINT64_MAX);
210
38 sync_point_manager_->DestroySyncPointClient(namespace_id_, client_id_); 211 sync_point_manager_->DestroySyncPointClient(namespace_id_, client_id_);
39 } 212 }
40 213
214 bool SyncPointClient::Wait(scoped_refptr<SyncPointClientState> release_state,
215 uint64_t release_count,
216 const base::Closure& wait_complete_callback) {
217 const uint32_t wait_order_number =
218 client_state_->order_data()->current_order_num();
219 return release_state->WaitForRelease(wait_order_number,
220 release_count,
221 wait_complete_callback);
222 }
223
224 bool SyncPointClient::WaitNonThreadSafe(
225 scoped_refptr<SyncPointClientState> release_state,
226 uint64_t release_count,
227 scoped_refptr<base::SingleThreadTaskRunner> runner,
228 const base::Closure& wait_complete_callback) {
229 return Wait(release_state,
230 release_count,
231 base::Bind(&RunOnThread, runner, wait_complete_callback));
232 }
233
234 void SyncPointClient::ReleaseFenceSync(uint64_t release) {
235 client_state_->ReleaseFenceSync(release);
236 }
237
41 SyncPointClient::SyncPointClient(SyncPointManager* sync_point_manager, 238 SyncPointClient::SyncPointClient(SyncPointManager* sync_point_manager,
42 scoped_refptr<SyncPointClientState> state, 239 scoped_refptr<SyncPointOrderData> order_data,
43 CommandBufferNamespace namespace_id, 240 CommandBufferNamespace namespace_id,
44 uint64_t client_id) 241 uint64_t client_id)
45 : sync_point_manager_(sync_point_manager), 242 : sync_point_manager_(sync_point_manager),
46 client_state_(state), 243 client_state_(new SyncPointClientState(order_data)),
47 namespace_id_(namespace_id), 244 namespace_id_(namespace_id),
48 client_id_(client_id) { 245 client_id_(client_id) {
49 } 246 }
50 247
51 SyncPointManager::SyncPointManager(bool allow_threaded_wait) 248 SyncPointManager::SyncPointManager(bool allow_threaded_wait)
52 : allow_threaded_wait_(allow_threaded_wait), 249 : allow_threaded_wait_(allow_threaded_wait),
53 // To reduce the risk that a sync point created in a previous GPU process 250 // To reduce the risk that a sync point created in a previous GPU process
54 // will be in flight in the next GPU process, randomize the starting sync 251 // will be in flight in the next GPU process, randomize the starting sync
55 // point number. http://crbug.com/373452 252 // point number. http://crbug.com/373452
56 next_sync_point_(base::RandInt(1, kMaxSyncBase)), 253 next_sync_point_(base::RandInt(1, kMaxSyncBase)),
57 retire_cond_var_(&lock_) { 254 retire_cond_var_(&lock_) {
58 global_order_num_.GetNext(); 255 global_order_num_.GetNext();
59 } 256 }
60 257
61 SyncPointManager::~SyncPointManager() { 258 SyncPointManager::~SyncPointManager() {
62 for (const ClientMap& client_map : client_maps_) { 259 for (const ClientMap& client_map : client_maps_) {
63 DCHECK(client_map.empty()); 260 DCHECK(client_map.empty());
64 } 261 }
65 } 262 }
66 263
67 scoped_ptr<SyncPointClient> SyncPointManager::CreateSyncPointClient( 264 scoped_ptr<SyncPointClient> SyncPointManager::CreateSyncPointClient(
68 scoped_refptr<SyncPointClientState> client_state, 265 scoped_refptr<SyncPointOrderData> order_data,
69 CommandBufferNamespace namespace_id, uint64_t client_id) { 266 CommandBufferNamespace namespace_id, uint64_t client_id) {
70 DCHECK_GE(namespace_id, 0); 267 DCHECK_GE(namespace_id, 0);
71 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_maps_)); 268 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_maps_));
72 base::AutoLock auto_lock(client_maps_lock_); 269 base::AutoLock auto_lock(client_maps_lock_);
73 270
74 ClientMap& client_map = client_maps_[namespace_id]; 271 ClientMap& client_map = client_maps_[namespace_id];
75 std::pair<ClientMap::iterator, bool> result = client_map.insert( 272 std::pair<ClientMap::iterator, bool> result = client_map.insert(
76 std::make_pair(client_id, new SyncPointClient(this, 273 std::make_pair(client_id, new SyncPointClient(this,
77 client_state, 274 order_data,
78 namespace_id, 275 namespace_id,
79 client_id))); 276 client_id)));
80 DCHECK(result.second); 277 DCHECK(result.second);
81 278
82 return make_scoped_ptr(result.first->second); 279 return make_scoped_ptr(result.first->second);
83 } 280 }
84 281
85 scoped_refptr<SyncPointClientState> SyncPointManager::GetSyncPointClientState( 282 scoped_refptr<SyncPointClientState> SyncPointManager::GetSyncPointClientState(
86 CommandBufferNamespace namespace_id, uint64_t client_id) { 283 CommandBufferNamespace namespace_id, uint64_t client_id) {
87 DCHECK_GE(namespace_id, 0); 284 DCHECK_GE(namespace_id, 0);
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_maps_)); 374 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_maps_));
178 375
179 base::AutoLock auto_lock(client_maps_lock_); 376 base::AutoLock auto_lock(client_maps_lock_);
180 ClientMap& client_map = client_maps_[namespace_id]; 377 ClientMap& client_map = client_maps_[namespace_id];
181 ClientMap::iterator it = client_map.find(client_id); 378 ClientMap::iterator it = client_map.find(client_id);
182 DCHECK(it != client_map.end()); 379 DCHECK(it != client_map.end());
183 client_map.erase(it); 380 client_map.erase(it);
184 } 381 }
185 382
186 } // namespace gpu 383 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698