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

Side by Side Diff: gpu/ipc/in_process_command_buffer.cc

Issue 2550583002: gpu: Thread-safe command buffer state lookup. (Closed)
Patch Set: state_lock_ -> last_state_lock_ Created 4 years 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/ipc/in_process_command_buffer.h" 5 #include "gpu/ipc/in_process_command_buffer.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <queue> 10 #include <queue>
(...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after
490 #if DCHECK_IS_ON() 490 #if DCHECK_IS_ON()
491 // This method shouldn't be called more than once. 491 // This method shouldn't be called more than once.
492 DCHECK(!context_lost_); 492 DCHECK(!context_lost_);
493 context_lost_ = true; 493 context_lost_ = true;
494 #endif 494 #endif
495 495
496 if (gpu_control_client_) 496 if (gpu_control_client_)
497 gpu_control_client_->OnGpuControlLostContext(); 497 gpu_control_client_->OnGpuControlLostContext();
498 } 498 }
499 499
500 CommandBuffer::State InProcessCommandBuffer::GetStateFast() {
501 CheckSequencedThread();
502 base::AutoLock lock(state_after_last_flush_lock_);
503 if (state_after_last_flush_.generation - last_state_.generation < 0x80000000U)
504 last_state_ = state_after_last_flush_;
505 return last_state_;
506 }
507
508 void InProcessCommandBuffer::QueueTask(bool out_of_order, 500 void InProcessCommandBuffer::QueueTask(bool out_of_order,
509 const base::Closure& task) { 501 const base::Closure& task) {
510 if (out_of_order) { 502 if (out_of_order) {
511 service_->ScheduleTask(task); 503 service_->ScheduleTask(task);
512 return; 504 return;
513 } 505 }
514 // Release the |task_queue_lock_| before calling ScheduleTask because 506 // Release the |task_queue_lock_| before calling ScheduleTask because
515 // the callback may get called immediately and attempt to acquire the lock. 507 // the callback may get called immediately and attempt to acquire the lock.
516 SyncPointManager* sync_manager = service_->sync_point_manager(); 508 SyncPointManager* sync_manager = service_->sync_point_manager();
517 uint32_t order_num = 509 uint32_t order_num =
(...skipping 18 matching lines...) Expand all
536 sync_point_order_data_->PauseProcessingOrderNumber(task->order_number); 528 sync_point_order_data_->PauseProcessingOrderNumber(task->order_number);
537 return; 529 return;
538 } 530 }
539 sync_point_order_data_->FinishProcessingOrderNumber(task->order_number); 531 sync_point_order_data_->FinishProcessingOrderNumber(task->order_number);
540 task_queue_.pop(); 532 task_queue_.pop();
541 } 533 }
542 } 534 }
543 535
544 CommandBuffer::State InProcessCommandBuffer::GetLastState() { 536 CommandBuffer::State InProcessCommandBuffer::GetLastState() {
545 CheckSequencedThread(); 537 CheckSequencedThread();
538 base::AutoLock lock(last_state_lock_);
546 return last_state_; 539 return last_state_;
547 } 540 }
548 541
549 int32_t InProcessCommandBuffer::GetLastToken() { 542 void InProcessCommandBuffer::UpdateLastStateOnGpuThread() {
550 CheckSequencedThread(); 543 CheckSequencedThread();
551 GetStateFast(); 544 command_buffer_lock_.AssertAcquired();
552 return last_state_.token; 545 base::AutoLock lock(last_state_lock_);
546 State state = command_buffer_->GetLastState();
547 if (state.generation - last_state_.generation < 0x80000000U)
548 last_state_ = state;
553 } 549 }
554 550
555 void InProcessCommandBuffer::FlushOnGpuThread(int32_t put_offset) { 551 void InProcessCommandBuffer::FlushOnGpuThread(int32_t put_offset) {
556 CheckSequencedThread(); 552 CheckSequencedThread();
557 ScopedEvent handle_flush(&flush_event_); 553 ScopedEvent handle_flush(&flush_event_);
558 base::AutoLock lock(command_buffer_lock_); 554 base::AutoLock lock(command_buffer_lock_);
559 555
560 { 556 command_buffer_->Flush(put_offset);
561 command_buffer_->Flush(put_offset); 557 // Update state before signaling the flush event.
562 { 558 UpdateLastStateOnGpuThread();
563 // Update state before signaling the flush event.
564 base::AutoLock lock(state_after_last_flush_lock_);
565 state_after_last_flush_ = command_buffer_->GetLastState();
566 }
567 }
568 559
569 // If we've processed all pending commands but still have pending queries, 560 // If we've processed all pending commands but still have pending queries,
570 // pump idle work until the query is passed. 561 // pump idle work until the query is passed.
571 if (put_offset == state_after_last_flush_.get_offset && 562 if (put_offset == command_buffer_->GetLastState().get_offset &&
572 (executor_->HasMoreIdleWork() || executor_->HasPendingQueries())) { 563 (executor_->HasMoreIdleWork() || executor_->HasPendingQueries())) {
573 ScheduleDelayedWorkOnGpuThread(); 564 ScheduleDelayedWorkOnGpuThread();
574 } 565 }
575 } 566 }
576 567
577 void InProcessCommandBuffer::PerformDelayedWorkOnGpuThread() { 568 void InProcessCommandBuffer::PerformDelayedWorkOnGpuThread() {
578 CheckSequencedThread(); 569 CheckSequencedThread();
579 delayed_work_pending_ = false; 570 delayed_work_pending_ = false;
580 base::AutoLock lock(command_buffer_lock_); 571 base::AutoLock lock(command_buffer_lock_);
581 if (MakeCurrent()) { 572 if (MakeCurrent()) {
(...skipping 10 matching lines...) Expand all
592 if (delayed_work_pending_) 583 if (delayed_work_pending_)
593 return; 584 return;
594 delayed_work_pending_ = true; 585 delayed_work_pending_ = true;
595 service_->ScheduleDelayedWork( 586 service_->ScheduleDelayedWork(
596 base::Bind(&InProcessCommandBuffer::PerformDelayedWorkOnGpuThread, 587 base::Bind(&InProcessCommandBuffer::PerformDelayedWorkOnGpuThread,
597 gpu_thread_weak_ptr_)); 588 gpu_thread_weak_ptr_));
598 } 589 }
599 590
600 void InProcessCommandBuffer::Flush(int32_t put_offset) { 591 void InProcessCommandBuffer::Flush(int32_t put_offset) {
601 CheckSequencedThread(); 592 CheckSequencedThread();
602 if (last_state_.error != gpu::error::kNoError) 593 if (GetLastState().error != gpu::error::kNoError)
603 return; 594 return;
604 595
605 if (last_put_offset_ == put_offset) 596 if (last_put_offset_ == put_offset)
606 return; 597 return;
607 598
608 last_put_offset_ = put_offset; 599 last_put_offset_ = put_offset;
609 base::Closure task = base::Bind(&InProcessCommandBuffer::FlushOnGpuThread, 600 base::Closure task = base::Bind(&InProcessCommandBuffer::FlushOnGpuThread,
610 gpu_thread_weak_ptr_, put_offset); 601 gpu_thread_weak_ptr_, put_offset);
611 QueueTask(false, task); 602 QueueTask(false, task);
612 603
613 flushed_fence_sync_release_ = next_fence_sync_release_ - 1; 604 flushed_fence_sync_release_ = next_fence_sync_release_ - 1;
614 } 605 }
615 606
616 void InProcessCommandBuffer::OrderingBarrier(int32_t put_offset) { 607 void InProcessCommandBuffer::OrderingBarrier(int32_t put_offset) {
617 Flush(put_offset); 608 Flush(put_offset);
618 } 609 }
619 610
620 void InProcessCommandBuffer::WaitForTokenInRange(int32_t start, int32_t end) { 611 CommandBuffer::State InProcessCommandBuffer::WaitForTokenInRange(int32_t start,
612 int32_t end) {
621 CheckSequencedThread(); 613 CheckSequencedThread();
622 while (!InRange(start, end, GetLastToken()) && 614 State last_state = GetLastState();
623 last_state_.error == gpu::error::kNoError) { 615 while (!InRange(start, end, last_state.token) &&
616 last_state.error == gpu::error::kNoError) {
624 flush_event_.Wait(); 617 flush_event_.Wait();
618 last_state = GetLastState();
625 } 619 }
620 return last_state;
626 } 621 }
627 622
628 void InProcessCommandBuffer::WaitForGetOffsetInRange(int32_t start, 623 CommandBuffer::State InProcessCommandBuffer::WaitForGetOffsetInRange(
629 int32_t end) { 624 int32_t start,
625 int32_t end) {
630 CheckSequencedThread(); 626 CheckSequencedThread();
631 627 State last_state = GetLastState();
632 GetStateFast(); 628 while (!InRange(start, end, last_state.get_offset) &&
633 while (!InRange(start, end, last_state_.get_offset) && 629 last_state.error == gpu::error::kNoError) {
634 last_state_.error == gpu::error::kNoError) {
635 flush_event_.Wait(); 630 flush_event_.Wait();
636 GetStateFast(); 631 last_state = GetLastState();
637 } 632 }
633 return last_state;
638 } 634 }
639 635
640 void InProcessCommandBuffer::SetGetBuffer(int32_t shm_id) { 636 void InProcessCommandBuffer::SetGetBuffer(int32_t shm_id) {
641 CheckSequencedThread(); 637 CheckSequencedThread();
642 if (last_state_.error != gpu::error::kNoError) 638 if (GetLastState().error != gpu::error::kNoError)
643 return; 639 return;
644 640
645 base::WaitableEvent completion( 641 base::WaitableEvent completion(
646 base::WaitableEvent::ResetPolicy::MANUAL, 642 base::WaitableEvent::ResetPolicy::MANUAL,
647 base::WaitableEvent::InitialState::NOT_SIGNALED); 643 base::WaitableEvent::InitialState::NOT_SIGNALED);
648 base::Closure task = 644 base::Closure task =
649 base::Bind(&InProcessCommandBuffer::SetGetBufferOnGpuThread, 645 base::Bind(&InProcessCommandBuffer::SetGetBufferOnGpuThread,
650 base::Unretained(this), shm_id, &completion); 646 base::Unretained(this), shm_id, &completion);
651 QueueTask(false, task); 647 QueueTask(false, task);
652 completion.Wait(); 648 completion.Wait();
653 649
654 { 650 last_put_offset_ = 0;
piman 2016/12/08 01:21:47 Nice catch!
655 base::AutoLock lock(state_after_last_flush_lock_);
656 state_after_last_flush_ = command_buffer_->GetLastState();
657 }
658 } 651 }
659 652
660 void InProcessCommandBuffer::SetGetBufferOnGpuThread( 653 void InProcessCommandBuffer::SetGetBufferOnGpuThread(
661 int32_t shm_id, 654 int32_t shm_id,
662 base::WaitableEvent* completion) { 655 base::WaitableEvent* completion) {
663 base::AutoLock lock(command_buffer_lock_); 656 base::AutoLock lock(command_buffer_lock_);
664 command_buffer_->SetGetBuffer(shm_id); 657 command_buffer_->SetGetBuffer(shm_id);
665 last_put_offset_ = 0; 658 UpdateLastStateOnGpuThread();
666 completion->Signal(); 659 completion->Signal();
667 } 660 }
668 661
669 scoped_refptr<Buffer> InProcessCommandBuffer::CreateTransferBuffer( 662 scoped_refptr<Buffer> InProcessCommandBuffer::CreateTransferBuffer(
670 size_t size, 663 size_t size,
671 int32_t* id) { 664 int32_t* id) {
672 CheckSequencedThread(); 665 CheckSequencedThread();
673 base::AutoLock lock(command_buffer_lock_); 666 base::AutoLock lock(command_buffer_lock_);
674 return command_buffer_->CreateTransferBuffer(size, id); 667 return command_buffer_->CreateTransferBuffer(size, id);
675 } 668 }
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after
1023 } 1016 }
1024 1017
1025 bool InProcessCommandBuffer::IsFenceSyncFlushed(uint64_t release) { 1018 bool InProcessCommandBuffer::IsFenceSyncFlushed(uint64_t release) {
1026 return release <= flushed_fence_sync_release_; 1019 return release <= flushed_fence_sync_release_;
1027 } 1020 }
1028 1021
1029 bool InProcessCommandBuffer::IsFenceSyncFlushReceived(uint64_t release) { 1022 bool InProcessCommandBuffer::IsFenceSyncFlushReceived(uint64_t release) {
1030 return IsFenceSyncFlushed(release); 1023 return IsFenceSyncFlushed(release);
1031 } 1024 }
1032 1025
1026 bool InProcessCommandBuffer::IsFenceSyncReleased(uint64_t release) {
1027 return release <= GetLastState().release_count;
1028 }
1029
1033 void InProcessCommandBuffer::SignalSyncToken(const SyncToken& sync_token, 1030 void InProcessCommandBuffer::SignalSyncToken(const SyncToken& sync_token,
1034 const base::Closure& callback) { 1031 const base::Closure& callback) {
1035 CheckSequencedThread(); 1032 CheckSequencedThread();
1036 QueueTask( 1033 QueueTask(
1037 true, 1034 true,
1038 base::Bind(&InProcessCommandBuffer::SignalSyncTokenOnGpuThread, 1035 base::Bind(&InProcessCommandBuffer::SignalSyncTokenOnGpuThread,
1039 base::Unretained(this), sync_token, WrapCallback(callback))); 1036 base::Unretained(this), sync_token, WrapCallback(callback)));
1040 } 1037 }
1041 1038
1042 bool InProcessCommandBuffer::CanWaitUnverifiedSyncToken( 1039 bool InProcessCommandBuffer::CanWaitUnverifiedSyncToken(
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1125 void InProcessCommandBuffer::SetSwapBuffersCompletionCallback( 1122 void InProcessCommandBuffer::SetSwapBuffersCompletionCallback(
1126 const SwapBuffersCompletionCallback& callback) { 1123 const SwapBuffersCompletionCallback& callback) {
1127 swap_buffers_completion_callback_ = callback; 1124 swap_buffers_completion_callback_ = callback;
1128 } 1125 }
1129 1126
1130 void InProcessCommandBuffer::SetUpdateVSyncParametersCallback( 1127 void InProcessCommandBuffer::SetUpdateVSyncParametersCallback(
1131 const UpdateVSyncParametersCallback& callback) { 1128 const UpdateVSyncParametersCallback& callback) {
1132 update_vsync_parameters_completion_callback_ = callback; 1129 update_vsync_parameters_completion_callback_ = callback;
1133 } 1130 }
1134 1131
1135 gpu::error::Error InProcessCommandBuffer::GetLastError() {
1136 CheckSequencedThread();
1137 return last_state_.error;
1138 }
1139
1140 namespace { 1132 namespace {
1141 1133
1142 void PostCallback( 1134 void PostCallback(
1143 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, 1135 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
1144 const base::Closure& callback) { 1136 const base::Closure& callback) {
1145 // The task_runner.get() check is to support using InProcessCommandBuffer on 1137 // The task_runner.get() check is to support using InProcessCommandBuffer on
1146 // a thread without a message loop. 1138 // a thread without a message loop.
1147 if (task_runner.get() && !task_runner->BelongsToCurrentThread()) { 1139 if (task_runner.get() && !task_runner->BelongsToCurrentThread()) {
1148 task_runner->PostTask(FROM_HERE, callback); 1140 task_runner->PostTask(FROM_HERE, callback);
1149 } else { 1141 } else {
(...skipping 23 matching lines...) Expand all
1173 return wrapped_callback; 1165 return wrapped_callback;
1174 } 1166 }
1175 1167
1176 InProcessCommandBuffer::GpuTask::GpuTask(const base::Closure& callback, 1168 InProcessCommandBuffer::GpuTask::GpuTask(const base::Closure& callback,
1177 uint32_t order_number) 1169 uint32_t order_number)
1178 : callback(callback), order_number(order_number) {} 1170 : callback(callback), order_number(order_number) {}
1179 1171
1180 InProcessCommandBuffer::GpuTask::~GpuTask() {} 1172 InProcessCommandBuffer::GpuTask::~GpuTask() {}
1181 1173
1182 } // namespace gpu 1174 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698