| 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 #include "gpu/command_buffer/service/sync_point_manager.h" | 5 #include "gpu/command_buffer/service/sync_point_manager.h" |
| 6 | 6 |
| 7 #include <limits.h> | 7 #include <limits.h> |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 #include <stdint.h> | 9 #include <stdint.h> |
| 10 | 10 |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 if (order_fence_queue_.top().order_num < order_num) { | 81 if (order_fence_queue_.top().order_num < order_num) { |
| 82 ensure_releases.push_back(order_fence); | 82 ensure_releases.push_back(order_fence); |
| 83 order_fence_queue_.pop(); | 83 order_fence_queue_.pop(); |
| 84 continue; | 84 continue; |
| 85 } | 85 } |
| 86 break; | 86 break; |
| 87 } | 87 } |
| 88 } | 88 } |
| 89 | 89 |
| 90 for (OrderFence& order_fence : ensure_releases) { | 90 for (OrderFence& order_fence : ensure_releases) { |
| 91 order_fence.client_state->EnsureReleased(order_fence.fence_release); | 91 order_fence.client_state->EnsureWaitReleased(order_fence.fence_release, |
| 92 order_fence.release_callback); |
| 92 } | 93 } |
| 93 } | 94 } |
| 94 | 95 |
| 95 void SyncPointOrderData::PauseProcessingOrderNumber(uint32_t order_num) { | 96 void SyncPointOrderData::PauseProcessingOrderNumber(uint32_t order_num) { |
| 96 DCHECK(processing_thread_checker_.CalledOnValidThread()); | 97 DCHECK(processing_thread_checker_.CalledOnValidThread()); |
| 97 DCHECK_EQ(current_order_num_, order_num); | 98 DCHECK_EQ(current_order_num_, order_num); |
| 98 DCHECK(!paused_); | 99 DCHECK(!paused_); |
| 99 paused_ = true; | 100 paused_ = true; |
| 100 } | 101 } |
| 101 | 102 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 119 if (order_fence_queue_.top().order_num <= order_num) { | 120 if (order_fence_queue_.top().order_num <= order_num) { |
| 120 ensure_releases.push_back(order_fence); | 121 ensure_releases.push_back(order_fence); |
| 121 order_fence_queue_.pop(); | 122 order_fence_queue_.pop(); |
| 122 continue; | 123 continue; |
| 123 } | 124 } |
| 124 break; | 125 break; |
| 125 } | 126 } |
| 126 } | 127 } |
| 127 | 128 |
| 128 for (OrderFence& order_fence : ensure_releases) { | 129 for (OrderFence& order_fence : ensure_releases) { |
| 129 order_fence.client_state->EnsureReleased(order_fence.fence_release); | 130 order_fence.client_state->EnsureWaitReleased(order_fence.fence_release, |
| 131 order_fence.release_callback); |
| 130 } | 132 } |
| 131 } | 133 } |
| 132 | 134 |
| 133 SyncPointOrderData::OrderFence::OrderFence( | 135 SyncPointOrderData::OrderFence::OrderFence( |
| 134 uint32_t order, | 136 uint32_t order, |
| 135 uint64_t release, | 137 uint64_t release, |
| 138 const base::Closure& callback, |
| 136 scoped_refptr<SyncPointClientState> state) | 139 scoped_refptr<SyncPointClientState> state) |
| 137 : order_num(order), fence_release(release), client_state(state) {} | 140 : order_num(order), |
| 141 fence_release(release), |
| 142 release_callback(callback), |
| 143 client_state(state) {} |
| 138 | 144 |
| 139 SyncPointOrderData::OrderFence::OrderFence(const OrderFence& other) = default; | 145 SyncPointOrderData::OrderFence::OrderFence(const OrderFence& other) = default; |
| 140 | 146 |
| 141 SyncPointOrderData::OrderFence::~OrderFence() {} | 147 SyncPointOrderData::OrderFence::~OrderFence() {} |
| 142 | 148 |
| 143 SyncPointOrderData::SyncPointOrderData() | 149 SyncPointOrderData::SyncPointOrderData() |
| 144 : current_order_num_(0), | 150 : current_order_num_(0), |
| 145 paused_(false), | 151 paused_(false), |
| 146 destroyed_(false), | 152 destroyed_(false), |
| 147 processed_order_num_(0), | 153 processed_order_num_(0), |
| 148 unprocessed_order_num_(0) {} | 154 unprocessed_order_num_(0) {} |
| 149 | 155 |
| 150 SyncPointOrderData::~SyncPointOrderData() {} | 156 SyncPointOrderData::~SyncPointOrderData() {} |
| 151 | 157 |
| 152 bool SyncPointOrderData::ValidateReleaseOrderNumber( | 158 bool SyncPointOrderData::ValidateReleaseOrderNumber( |
| 153 scoped_refptr<SyncPointClientState> client_state, | 159 scoped_refptr<SyncPointClientState> client_state, |
| 154 uint32_t wait_order_num, | 160 uint32_t wait_order_num, |
| 155 uint64_t fence_release) { | 161 uint64_t fence_release, |
| 162 const base::Closure& release_callback) { |
| 156 base::AutoLock auto_lock(lock_); | 163 base::AutoLock auto_lock(lock_); |
| 157 if (destroyed_) | 164 if (destroyed_) |
| 158 return false; | 165 return false; |
| 159 | 166 |
| 160 // Release should have a possible unprocessed order number lower | 167 // Release should have a possible unprocessed order number lower |
| 161 // than the wait order number. | 168 // than the wait order number. |
| 162 if ((processed_order_num_ + 1) >= wait_order_num) | 169 if ((processed_order_num_ + 1) >= wait_order_num) |
| 163 return false; | 170 return false; |
| 164 | 171 |
| 165 // Release should have more unprocessed numbers if we are waiting. | 172 // Release should have more unprocessed numbers if we are waiting. |
| 166 if (unprocessed_order_num_ <= processed_order_num_) | 173 if (unprocessed_order_num_ <= processed_order_num_) |
| 167 return false; | 174 return false; |
| 168 | 175 |
| 169 // So far it could be valid, but add an order fence guard to be sure it | 176 // So far it could be valid, but add an order fence guard to be sure it |
| 170 // gets released eventually. | 177 // gets released eventually. |
| 171 const uint32_t expected_order_num = | 178 const uint32_t expected_order_num = |
| 172 std::min(unprocessed_order_num_, wait_order_num); | 179 std::min(unprocessed_order_num_, wait_order_num); |
| 173 order_fence_queue_.push( | 180 order_fence_queue_.push(OrderFence(expected_order_num, fence_release, |
| 174 OrderFence(expected_order_num, fence_release, client_state)); | 181 release_callback, client_state)); |
| 175 return true; | 182 return true; |
| 176 } | 183 } |
| 177 | 184 |
| 178 SyncPointClientState::ReleaseCallback::ReleaseCallback( | 185 SyncPointClientState::ReleaseCallback::ReleaseCallback( |
| 179 uint64_t release, | 186 uint64_t release, |
| 180 const base::Closure& callback) | 187 const base::Closure& callback) |
| 181 : release_count(release), callback_closure(callback) {} | 188 : release_count(release), callback_closure(callback) {} |
| 182 | 189 |
| 183 SyncPointClientState::ReleaseCallback::ReleaseCallback( | 190 SyncPointClientState::ReleaseCallback::ReleaseCallback( |
| 184 const ReleaseCallback& other) = default; | 191 const ReleaseCallback& other) = default; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 196 CommandBufferId client_id, | 203 CommandBufferId client_id, |
| 197 uint32_t wait_order_num, | 204 uint32_t wait_order_num, |
| 198 uint64_t release, | 205 uint64_t release, |
| 199 const base::Closure& callback) { | 206 const base::Closure& callback) { |
| 200 // Lock must be held the whole time while we validate otherwise it could be | 207 // Lock must be held the whole time while we validate otherwise it could be |
| 201 // released while we are checking. | 208 // released while we are checking. |
| 202 { | 209 { |
| 203 base::AutoLock auto_lock(fence_sync_lock_); | 210 base::AutoLock auto_lock(fence_sync_lock_); |
| 204 if (release > fence_sync_release_) { | 211 if (release > fence_sync_release_) { |
| 205 if (!order_data_->ValidateReleaseOrderNumber(this, wait_order_num, | 212 if (!order_data_->ValidateReleaseOrderNumber(this, wait_order_num, |
| 206 release)) { | 213 release, callback)) { |
| 207 return false; | 214 return false; |
| 208 } else { | 215 } else { |
| 209 // Add the callback which will be called upon release. | 216 // Add the callback which will be called upon release. |
| 210 release_callback_queue_.push(ReleaseCallback(release, callback)); | 217 release_callback_queue_.push(ReleaseCallback(release, callback)); |
| 211 if (!on_wait_callback_.is_null()) | 218 if (!on_wait_callback_.is_null()) |
| 212 on_wait_callback_.Run(namespace_id, client_id); | 219 on_wait_callback_.Run(namespace_id, client_id); |
| 213 return true; | 220 return true; |
| 214 } | 221 } |
| 215 } | 222 } |
| 216 } | 223 } |
| 217 | 224 |
| 218 // Already released, run the callback now. | 225 // Already released, run the callback now. |
| 219 callback.Run(); | 226 callback.Run(); |
| 220 return true; | 227 return true; |
| 221 } | 228 } |
| 222 | 229 |
| 223 void SyncPointClientState::ReleaseFenceSync(uint64_t release) { | 230 void SyncPointClientState::ReleaseFenceSync(uint64_t release) { |
| 224 // Call callbacks without the lock to avoid possible deadlocks. | 231 // Call callbacks without the lock to avoid possible deadlocks. |
| 225 std::vector<base::Closure> callback_list; | 232 std::vector<base::Closure> callback_list; |
| 226 { | 233 { |
| 227 base::AutoLock auto_lock(fence_sync_lock_); | 234 base::AutoLock auto_lock(fence_sync_lock_); |
| 228 ReleaseFenceSyncLocked(release, &callback_list); | 235 DCHECK_GT(release, fence_sync_release_); |
| 236 |
| 237 fence_sync_release_ = release; |
| 238 while (!release_callback_queue_.empty() && |
| 239 release_callback_queue_.top().release_count <= release) { |
| 240 callback_list.push_back(release_callback_queue_.top().callback_closure); |
| 241 release_callback_queue_.pop(); |
| 242 } |
| 229 } | 243 } |
| 230 | 244 |
| 231 for (const base::Closure& closure : callback_list) { | 245 for (const base::Closure& closure : callback_list) { |
| 232 closure.Run(); | 246 closure.Run(); |
| 233 } | 247 } |
| 234 } | 248 } |
| 235 | 249 |
| 236 void SyncPointClientState::EnsureReleased(uint64_t release) { | 250 void SyncPointClientState::EnsureWaitReleased(uint64_t release, |
| 251 const base::Closure& callback) { |
| 237 // Call callbacks without the lock to avoid possible deadlocks. | 252 // Call callbacks without the lock to avoid possible deadlocks. |
| 238 std::vector<base::Closure> callback_list; | 253 bool call_callback = false; |
| 239 { | 254 { |
| 240 base::AutoLock auto_lock(fence_sync_lock_); | 255 base::AutoLock auto_lock(fence_sync_lock_); |
| 241 if (release <= fence_sync_release_) | 256 if (release <= fence_sync_release_) |
| 242 return; | 257 return; |
| 243 | 258 |
| 244 ReleaseFenceSyncLocked(release, &callback_list); | 259 std::vector<ReleaseCallback> popped_callbacks; |
| 260 popped_callbacks.reserve(release_callback_queue_.size()); |
| 261 |
| 262 while (!release_callback_queue_.empty() && |
| 263 release_callback_queue_.top().release_count <= release) { |
| 264 const ReleaseCallback& top_item = release_callback_queue_.top(); |
| 265 if (top_item.release_count == release && |
| 266 top_item.callback_closure.Equals(callback)) { |
| 267 // Call the callback, and discard this item from the callback queue. |
| 268 call_callback = true; |
| 269 } else { |
| 270 // Store the item to be placed back into the callback queue later. |
| 271 popped_callbacks.push_back(top_item); |
| 272 } |
| 273 release_callback_queue_.pop(); |
| 274 } |
| 275 |
| 276 // Add back in popped items. |
| 277 for (const ReleaseCallback& popped_callback : popped_callbacks) { |
| 278 release_callback_queue_.push(popped_callback); |
| 279 } |
| 245 } | 280 } |
| 246 | 281 |
| 247 for (const base::Closure& closure : callback_list) { | 282 if (call_callback) { |
| 248 closure.Run(); | 283 // This effectively releases the wait without releasing the fence. |
| 284 callback.Run(); |
| 249 } | 285 } |
| 250 } | 286 } |
| 251 | 287 |
| 252 void SyncPointClientState::ReleaseFenceSyncLocked( | |
| 253 uint64_t release, | |
| 254 std::vector<base::Closure>* callback_list) { | |
| 255 fence_sync_lock_.AssertAcquired(); | |
| 256 DCHECK_GT(release, fence_sync_release_); | |
| 257 | |
| 258 fence_sync_release_ = release; | |
| 259 while (!release_callback_queue_.empty() && | |
| 260 release_callback_queue_.top().release_count <= release) { | |
| 261 callback_list->push_back(release_callback_queue_.top().callback_closure); | |
| 262 release_callback_queue_.pop(); | |
| 263 } | |
| 264 } | |
| 265 | |
| 266 void SyncPointClientState::SetOnWaitCallback(const OnWaitCallback& callback) { | 288 void SyncPointClientState::SetOnWaitCallback(const OnWaitCallback& callback) { |
| 267 on_wait_callback_ = callback; | 289 on_wait_callback_ = callback; |
| 268 } | 290 } |
| 269 | 291 |
| 270 SyncPointClient::~SyncPointClient() { | 292 SyncPointClient::~SyncPointClient() { |
| 271 if (namespace_id_ != gpu::CommandBufferNamespace::INVALID) { | 293 if (namespace_id_ != gpu::CommandBufferNamespace::INVALID) { |
| 272 // Release all fences on destruction. | 294 // Release all fences on destruction. |
| 273 client_state_->ReleaseFenceSync(UINT64_MAX); | 295 client_state_->ReleaseFenceSync(UINT64_MAX); |
| 274 | 296 |
| 275 sync_point_manager_->DestroySyncPointClient(namespace_id_, client_id_); | 297 sync_point_manager_->DestroySyncPointClient(namespace_id_, client_id_); |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 419 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_maps_)); | 441 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_maps_)); |
| 420 | 442 |
| 421 base::AutoLock auto_lock(client_maps_lock_); | 443 base::AutoLock auto_lock(client_maps_lock_); |
| 422 ClientMap& client_map = client_maps_[namespace_id]; | 444 ClientMap& client_map = client_maps_[namespace_id]; |
| 423 ClientMap::iterator it = client_map.find(client_id); | 445 ClientMap::iterator it = client_map.find(client_id); |
| 424 DCHECK(it != client_map.end()); | 446 DCHECK(it != client_map.end()); |
| 425 client_map.erase(it); | 447 client_map.erase(it); |
| 426 } | 448 } |
| 427 | 449 |
| 428 } // namespace gpu | 450 } // namespace gpu |
| OLD | NEW |