diff options
author | sievers@chromium.org <sievers@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-25 18:13:27 +0000 |
---|---|---|
committer | sievers@chromium.org <sievers@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-25 18:13:27 +0000 |
commit | efaff84fd25ab16edd8ac5c9e9ab3cf3b8d0c911 (patch) | |
tree | d507da03a9c35c79d10bd22607588fa88a3f0182 /gpu/command_buffer | |
parent | e332fe24f39bb8fb42024aba1d9114b618ea1936 (diff) | |
download | chromium_src-efaff84fd25ab16edd8ac5c9e9ab3cf3b8d0c911.zip chromium_src-efaff84fd25ab16edd8ac5c9e9ab3cf3b8d0c911.tar.gz chromium_src-efaff84fd25ab16edd8ac5c9e9ab3cf3b8d0c911.tar.bz2 |
GLInProcessContext: Implement global sync points
Replaces the implementation that relied on flush ordering since that
is not guaranteed when running different service threads.
NOTRY=True
BUG=332146
Review URL: https://codereview.chromium.org/168183003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@253201 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu/command_buffer')
-rw-r--r-- | gpu/command_buffer/service/in_process_command_buffer.cc | 91 | ||||
-rw-r--r-- | gpu/command_buffer/service/in_process_command_buffer.h | 2 |
2 files changed, 91 insertions, 2 deletions
diff --git a/gpu/command_buffer/service/in_process_command_buffer.cc b/gpu/command_buffer/service/in_process_command_buffer.cc index 5bc7ded..b7feee9 100644 --- a/gpu/command_buffer/service/in_process_command_buffer.cc +++ b/gpu/command_buffer/service/in_process_command_buffer.cc @@ -5,6 +5,7 @@ #include "gpu/command_buffer/service/in_process_command_buffer.h" #include <queue> +#include <set> #include <utility> #include <GLES2/gl2.h> @@ -21,6 +22,7 @@ #include "base/memory/weak_ptr.h" #include "base/message_loop/message_loop_proxy.h" #include "base/sequence_checker.h" +#include "base/synchronization/condition_variable.h" #include "base/threading/thread.h" #include "gpu/command_buffer/service/command_buffer_service.h" #include "gpu/command_buffer/service/context_group.h" @@ -109,6 +111,71 @@ class ScopedEvent { base::WaitableEvent* event_; }; +class SyncPointManager { + public: + SyncPointManager(); + ~SyncPointManager(); + + uint32 GenerateSyncPoint(); + void RetireSyncPoint(uint32 sync_point); + + bool IsSyncPointPassed(uint32 sync_point); + void WaitSyncPoint(uint32 sync_point); + +private: + // This lock protects access to pending_sync_points_ and next_sync_point_ and + // is used with the ConditionVariable to signal when a sync point is retired. + base::Lock lock_; + std::set<uint32> pending_sync_points_; + uint32 next_sync_point_; + base::ConditionVariable cond_var_; +}; + +SyncPointManager::SyncPointManager() : next_sync_point_(0), cond_var_(&lock_) {} + +SyncPointManager::~SyncPointManager() { + DCHECK_EQ(pending_sync_points_.size(), 0U); +} + +uint32 SyncPointManager::GenerateSyncPoint() { + base::AutoLock lock(lock_); + uint32 sync_point = next_sync_point_++; + DCHECK_EQ(pending_sync_points_.count(sync_point), 0U); + pending_sync_points_.insert(sync_point); + return sync_point; +} + +void SyncPointManager::RetireSyncPoint(uint32 sync_point) { + base::AutoLock lock(lock_); + DCHECK(pending_sync_points_.count(sync_point)); + pending_sync_points_.erase(sync_point); + cond_var_.Broadcast(); +} + +bool SyncPointManager::IsSyncPointPassed(uint32 sync_point) { + base::AutoLock lock(lock_); + return pending_sync_points_.count(sync_point) == 0; +} + +void SyncPointManager::WaitSyncPoint(uint32 sync_point) { + base::AutoLock lock(lock_); + while (pending_sync_points_.count(sync_point)) { + cond_var_.Wait(); + } +} + +base::LazyInstance<SyncPointManager> g_sync_point_manager = + LAZY_INSTANCE_INITIALIZER; + +bool WaitSyncPoint(uint32 sync_point) { + g_sync_point_manager.Get().WaitSyncPoint(sync_point); + return true; +} + +void RetireSyncPoint(uint32 sync_point) { + g_sync_point_manager.Get().RetireSyncPoint(sync_point); +} + } // anonyous namespace InProcessCommandBuffer::Service::Service() {} @@ -347,6 +414,7 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( decoder_->SetResizeCallback(base::Bind( &InProcessCommandBuffer::OnResizeView, gpu_thread_weak_ptr_)); } + decoder_->SetWaitSyncPointCallback(base::Bind(&WaitSyncPoint)); return true; } @@ -552,13 +620,32 @@ void InProcessCommandBuffer::DestroyGpuMemoryBuffer(int32 id) { } uint32 InProcessCommandBuffer::InsertSyncPoint() { - return 0; + uint32 sync_point = g_sync_point_manager.Get().GenerateSyncPoint(); + QueueTask(base::Bind(&RetireSyncPoint, sync_point)); + return sync_point; } void InProcessCommandBuffer::SignalSyncPoint(unsigned sync_point, const base::Closure& callback) { CheckSequencedThread(); - QueueTask(WrapCallback(callback)); + QueueTask(base::Bind(&InProcessCommandBuffer::SignalSyncPointOnGpuThread, + base::Unretained(this), + sync_point, + WrapCallback(callback))); +} + +void InProcessCommandBuffer::SignalSyncPointOnGpuThread( + unsigned sync_point, + const base::Closure& callback) { + if (g_sync_point_manager.Get().IsSyncPointPassed(sync_point)) { + callback.Run(); + } else { + service_->ScheduleIdleWork( + base::Bind(&InProcessCommandBuffer::SignalSyncPointOnGpuThread, + gpu_thread_weak_ptr_, + sync_point, + callback)); + } } void InProcessCommandBuffer::SignalQuery(unsigned query, diff --git a/gpu/command_buffer/service/in_process_command_buffer.h b/gpu/command_buffer/service/in_process_command_buffer.h index 199a294..bd83502 100644 --- a/gpu/command_buffer/service/in_process_command_buffer.h +++ b/gpu/command_buffer/service/in_process_command_buffer.h @@ -174,6 +174,8 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, State GetStateFast(); void QueueTask(const base::Closure& task) { service_->ScheduleTask(task); } void CheckSequencedThread(); + void SignalSyncPointOnGpuThread(uint32 sync_point, + const base::Closure& callback); // Callbacks: void OnContextLost(); |