#ifndef GPU_COMMAND_BUFFER_SERVICE_SYNC_POINT_MANAGER_H_
#define GPU_COMMAND_BUFFER_SERVICE_SYNC_POINT_MANAGER_H_
#include <stdint.h>
#include <functional>
#include <memory>
#include <queue>
#include <vector>
#include "base/atomic_sequence_num.h"
#include "base/check.h"
#include "base/containers/flat_map.h"
#include "base/containers/queue.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/synchronization/lock.h"
#include "base/thread_annotations.h"
#include "base/threading/thread_checker.h"
#include "gpu/command_buffer/common/command_buffer_id.h"
#include "gpu/command_buffer/common/constants.h"
#include "gpu/command_buffer/common/sync_token.h"
#include "gpu/command_buffer/service/sequence_id.h"
#include "gpu/gpu_export.h"
namespace base {
class SingleThreadTaskRunner;
}
namespace gpu {
class SyncPointClient;
class SyncPointClientState;
class SyncPointManager;
class GPU_EXPORT SyncPointOrderData
: public base::RefCountedThreadSafe<SyncPointOrderData> {
public:
SyncPointOrderData(const SyncPointOrderData&) = delete;
SyncPointOrderData& operator=(const SyncPointOrderData&) = delete;
void Destroy() LOCKS_EXCLUDED(lock_);
SequenceId sequence_id() { return sequence_id_; }
uint32_t processed_order_num() const {
base::AutoLock auto_lock(lock_);
return processed_order_num_;
}
uint32_t unprocessed_order_num() const {
base::AutoLock auto_lock(lock_);
return last_unprocessed_order_num_;
}
uint32_t current_order_num() const {
DCHECK(processing_thread_checker_.CalledOnValidThread());
return current_order_num_;
}
bool IsProcessingOrderNumber() {
DCHECK(processing_thread_checker_.CalledOnValidThread());
return !paused_ && current_order_num_ > processed_order_num();
}
uint32_t GenerateUnprocessedOrderNumber();
void BeginProcessingOrderNumber(uint32_t order_num);
void PauseProcessingOrderNumber(uint32_t order_num);
void FinishProcessingOrderNumber(uint32_t order_num);
private:
friend class base::RefCountedThreadSafe<SyncPointOrderData>;
friend class SyncPointManager;
friend class SyncPointClientState;
struct OrderFence {
uint32_t order_num;
uint64_t fence_release;
scoped_refptr<SyncPointClientState> client_state;
uint64_t callback_id;
OrderFence(uint32_t order,
uint64_t release,
scoped_refptr<SyncPointClientState> state,
uint64_t callback_id);
OrderFence(const OrderFence& other);
~OrderFence();
bool operator>(const OrderFence& rhs) const {
return std::tie(order_num, fence_release) >
std::tie(rhs.order_num, rhs.fence_release);
}
};
typedef std::
priority_queue<OrderFence, std::vector<OrderFence>, std::greater<>>
OrderFenceQueue;
SyncPointOrderData(SyncPointManager* sync_point_manager,
SequenceId seqeunce_id);
~SyncPointOrderData();
void DestroyInternal() LOCKS_EXCLUDED(lock_);
uint64_t ValidateReleaseOrderNumber(
scoped_refptr<SyncPointClientState> client_state,
uint32_t wait_order_num,
uint64_t fence_release) LOCKS_EXCLUDED(lock_);
const raw_ptr<SyncPointManager> sync_point_manager_;
const SequenceId sequence_id_;
uint64_t current_callback_id_ GUARDED_BY(lock_) = 0;
base::ThreadChecker processing_thread_checker_;
uint32_t current_order_num_ = 0;
bool paused_ = false;
mutable base::Lock lock_;
bool destroyed_ GUARDED_BY(lock_) = false;
uint32_t processed_order_num_ GUARDED_BY(lock_) = 0;
uint32_t last_unprocessed_order_num_ GUARDED_BY(lock_) = 0;
base::queue<uint32_t> unprocessed_order_nums_ GUARDED_BY(lock_);
OrderFenceQueue order_fence_queue_ GUARDED_BY(lock_);
};
class GPU_EXPORT SyncPointClientState
: public base::RefCountedThreadSafe<SyncPointClientState> {
public:
SyncPointClientState(const SyncPointClientState&) = delete;
SyncPointClientState& operator=(const SyncPointClientState&) = delete;
void Destroy() LOCKS_EXCLUDED(fence_sync_lock_);
CommandBufferNamespace namespace_id() const { return namespace_id_; }
CommandBufferId command_buffer_id() const { return command_buffer_id_; }
SequenceId sequence_id() const { return order_data_->sequence_id(); }
bool Wait(const SyncToken& sync_token, base::OnceClosure callback)
LOCKS_EXCLUDED(fence_sync_lock_);
bool WaitNonThreadSafe(
const SyncToken& sync_token,
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
base::OnceClosure callback) LOCKS_EXCLUDED(fence_sync_lock_);
void ReleaseFenceSync(uint64_t release) LOCKS_EXCLUDED(fence_sync_lock_);
private:
friend class base::RefCountedThreadSafe<SyncPointClientState>;
friend class SyncPointManager;
friend class SyncPointOrderData;
struct ReleaseCallback {
uint64_t release_count;
base::OnceClosure callback_closure;
uint64_t callback_id;
ReleaseCallback(uint64_t release,
base::OnceClosure callback,
uint64_t callback_id);
ReleaseCallback(ReleaseCallback&& other);
~ReleaseCallback();
ReleaseCallback& operator=(ReleaseCallback&& other) = default;
bool operator>(const ReleaseCallback& rhs) const {
return release_count > rhs.release_count;
}
};
typedef std::priority_queue<ReleaseCallback,
std::vector<ReleaseCallback>,
std::greater<>>
ReleaseCallbackQueue;
SyncPointClientState(SyncPointManager* sync_point_manager,
scoped_refptr<SyncPointOrderData> order_data,
CommandBufferNamespace namespace_id,
CommandBufferId command_buffer_id);
~SyncPointClientState();
std::vector<base::OnceClosure> DestroyAndReturnCallbacks()
LOCKS_EXCLUDED(fence_sync_lock_);
bool IsFenceSyncReleased(uint64_t release) LOCKS_EXCLUDED(fence_sync_lock_);
bool WaitForRelease(uint64_t release,
uint32_t wait_order_num,
base::OnceClosure callback)
LOCKS_EXCLUDED(fence_sync_lock_);
void EnsureWaitReleased(uint64_t release, uint64_t callback_id)
LOCKS_EXCLUDED(fence_sync_lock_);
void ReleaseFenceSyncHelper(uint64_t release)
LOCKS_EXCLUDED(fence_sync_lock_);
raw_ptr<SyncPointManager> sync_point_manager_ = nullptr;
const scoped_refptr<SyncPointOrderData> order_data_;
const CommandBufferNamespace namespace_id_;
const CommandBufferId command_buffer_id_;
base::Lock fence_sync_lock_;
uint64_t fence_sync_release_ GUARDED_BY(fence_sync_lock_) = 0;
ReleaseCallbackQueue release_callback_queue_ GUARDED_BY(fence_sync_lock_);
};
class GPU_EXPORT SyncPointManager {
public:
SyncPointManager();
SyncPointManager(const SyncPointManager&) = delete;
SyncPointManager& operator=(const SyncPointManager&) = delete;
~SyncPointManager();
scoped_refptr<SyncPointOrderData> CreateSyncPointOrderData();
scoped_refptr<SyncPointClientState> CreateSyncPointClientState(
CommandBufferNamespace namespace_id,
CommandBufferId command_buffer_id,
SequenceId sequence_id);
bool IsSyncTokenReleased(const SyncToken& sync_token) LOCKS_EXCLUDED(lock_);
SequenceId GetSyncTokenReleaseSequenceId(const SyncToken& sync_token)
LOCKS_EXCLUDED(lock_);
uint32_t GetProcessedOrderNum() const LOCKS_EXCLUDED(lock_);
uint32_t GetUnprocessedOrderNum() const LOCKS_EXCLUDED(lock_);
bool Wait(const SyncToken& sync_token,
SequenceId sequence_id,
uint32_t wait_order_num,
base::OnceClosure callback) LOCKS_EXCLUDED(lock_);
bool WaitNonThreadSafe(
const SyncToken& sync_token,
SequenceId sequence_id,
uint32_t wait_order_num,
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
base::OnceClosure callback) LOCKS_EXCLUDED(lock_);
bool WaitOutOfOrder(const SyncToken& trusted_sync_token,
base::OnceClosure callback) LOCKS_EXCLUDED(lock_);
uint32_t GenerateOrderNumber();
void RemoveSyncPointOrderData(scoped_refptr<SyncPointOrderData> order_data)
LOCKS_EXCLUDED(lock_);
void DestroySyncPointClientState(
scoped_refptr<SyncPointClientState> client_state)
LOCKS_EXCLUDED(lock_, client_state->fence_sync_lock_);
private:
using ClientStateMap =
base::flat_map<CommandBufferId, scoped_refptr<SyncPointClientState>>;
using OrderDataMap =
base::flat_map<SequenceId, scoped_refptr<SyncPointOrderData>>;
scoped_refptr<SyncPointOrderData> GetSyncPointOrderData(
SequenceId sequence_id) EXCLUSIVE_LOCKS_REQUIRED(lock_);
scoped_refptr<SyncPointClientState> GetSyncPointClientState(
CommandBufferNamespace namespace_id,
CommandBufferId command_buffer_id) EXCLUSIVE_LOCKS_REQUIRED(lock_);
SequenceId GetSyncTokenReleaseSequenceIdInternal(const SyncToken& sync_token)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
base::AtomicSequenceNumber order_num_generator_;
ClientStateMap client_state_maps_[NUM_COMMAND_BUFFER_NAMESPACES] GUARDED_BY(
lock_);
OrderDataMap order_data_map_ GUARDED_BY(lock_);
SequenceId::Generator sequence_id_generator_ GUARDED_BY(lock_);
mutable base::Lock lock_;
};
}
#endif