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; |