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

Unified Diff: gpu/ipc/service/gpu_channel.cc

Issue 2814843002: gpu: GPU service scheduler. (Closed)
Patch Set: rebase Created 3 years, 8 months 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 side-by-side diff with in-line comments
Download patch
Index: gpu/ipc/service/gpu_channel.cc
diff --git a/gpu/ipc/service/gpu_channel.cc b/gpu/ipc/service/gpu_channel.cc
index 1d67b33ae2d0022e75a54dbdefcb57551c25c2d9..0d500deac425d4251d6a76e66dd7ccdd82418421 100644
--- a/gpu/ipc/service/gpu_channel.cc
+++ b/gpu/ipc/service/gpu_channel.cc
@@ -34,6 +34,7 @@
#include "gpu/command_buffer/service/image_factory.h"
#include "gpu/command_buffer/service/mailbox_manager.h"
#include "gpu/command_buffer/service/preemption_flag.h"
+#include "gpu/command_buffer/service/scheduler.h"
#include "gpu/ipc/common/gpu_messages.h"
#include "gpu/ipc/service/gpu_channel_manager.h"
#include "gpu/ipc/service/gpu_channel_manager_delegate.h"
@@ -99,21 +100,20 @@ void SyncChannelFilteredSender::RemoveFilter(IPC::MessageFilter* filter) {
GpuChannelMessageQueue::GpuChannelMessageQueue(
GpuChannel* channel,
+ scoped_refptr<SyncPointOrderData> sync_point_order_data,
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
scoped_refptr<PreemptionFlag> preempting_flag,
- scoped_refptr<PreemptionFlag> preempted_flag,
- SyncPointManager* sync_point_manager)
+ scoped_refptr<PreemptionFlag> preempted_flag)
: channel_(channel),
max_preemption_time_(
base::TimeDelta::FromMilliseconds(kMaxPreemptTimeMs)),
timer_(new base::OneShotTimer),
- sync_point_order_data_(sync_point_manager->CreateSyncPointOrderData()),
+ sync_point_order_data_(std::move(sync_point_order_data)),
main_task_runner_(std::move(main_task_runner)),
io_task_runner_(std::move(io_task_runner)),
preempting_flag_(std::move(preempting_flag)),
- preempted_flag_(std::move(preempted_flag)),
- sync_point_manager_(sync_point_manager) {
+ preempted_flag_(std::move(preempted_flag)) {
timer_->SetTaskRunner(io_task_runner_);
io_thread_checker_.DetachFromThread();
}
@@ -439,9 +439,11 @@ void GpuChannelMessageQueue::TransitionToWouldPreemptDescheduled() {
GpuChannelMessageFilter::GpuChannelMessageFilter(
GpuChannel* gpu_channel,
+ Scheduler* scheduler,
scoped_refptr<GpuChannelMessageQueue> message_queue,
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner)
: gpu_channel_(gpu_channel),
+ scheduler_(scheduler),
message_queue_(std::move(message_queue)),
main_task_runner_(std::move(main_task_runner)) {}
@@ -454,6 +456,21 @@ void GpuChannelMessageFilter::Destroy() {
gpu_channel_ = nullptr;
}
+void GpuChannelMessageFilter::AddRoute(int32_t route_id,
+ SequenceId sequence_id) {
+ base::AutoLock auto_lock(gpu_channel_lock_);
+ DCHECK(gpu_channel_);
+ DCHECK(scheduler_);
+ route_sequences_[route_id] = sequence_id;
+}
+
+void GpuChannelMessageFilter::RemoveRoute(int32_t route_id) {
+ base::AutoLock auto_lock(gpu_channel_lock_);
+ DCHECK(gpu_channel_);
+ DCHECK(scheduler_);
+ route_sequences_.erase(route_id);
+}
+
void GpuChannelMessageFilter::OnFilterAdded(IPC::Channel* channel) {
DCHECK(!ipc_channel_);
ipc_channel_ = channel;
@@ -504,6 +521,9 @@ void GpuChannelMessageFilter::RemoveChannelFilter(
bool GpuChannelMessageFilter::OnMessageReceived(const IPC::Message& message) {
DCHECK(ipc_channel_);
+ if (!gpu_channel_)
+ return MessageErrorHandler(message, "Channel destroyed");
+
if (message.should_unblock() || message.is_reply())
return MessageErrorHandler(message, "Unexpected message type");
@@ -530,6 +550,23 @@ bool GpuChannelMessageFilter::OnMessageReceived(const IPC::Message& message) {
main_task_runner_->PostTask(FROM_HERE,
base::Bind(&GpuChannel::HandleOutOfOrderMessage,
gpu_channel_->AsWeakPtr(), message));
+ } else if (scheduler_) {
+ SequenceId sequence_id = route_sequences_[message.routing_id()];
+ if (sequence_id.is_null())
+ return MessageErrorHandler(message, "Invalid route");
+
+ std::vector<SyncToken> sync_token_fences;
+ if (message.type() == GpuCommandBufferMsg_AsyncFlush::ID) {
+ GpuCommandBufferMsg_AsyncFlush::Param params;
+ if (!GpuCommandBufferMsg_AsyncFlush::Read(&message, &params))
+ return MessageErrorHandler(message, "Invalid flush message");
+ sync_token_fences = std::get<3>(params);
+ }
+
+ scheduler_->ScheduleTask(sequence_id,
+ base::BindOnce(&GpuChannel::HandleMessage,
+ gpu_channel_->AsWeakPtr(), message),
+ sync_token_fences);
} else {
// Message queue takes care of PostTask.
message_queue_->PushBackMessage(message);
@@ -561,6 +598,7 @@ FilteredSender::~FilteredSender() = default;
GpuChannel::GpuChannel(
GpuChannelManager* gpu_channel_manager,
+ Scheduler* scheduler,
SyncPointManager* sync_point_manager,
GpuWatchdogThread* watchdog,
scoped_refptr<gl::GLShareGroup> share_group,
@@ -573,6 +611,7 @@ GpuChannel::GpuChannel(
uint64_t client_tracing_id,
bool is_gpu_host)
: gpu_channel_manager_(gpu_channel_manager),
+ scheduler_(scheduler),
sync_point_manager_(sync_point_manager),
preempting_flag_(preempting_flag),
preempted_flag_(preempted_flag),
@@ -585,14 +624,17 @@ GpuChannel::GpuChannel(
watchdog_(watchdog),
is_gpu_host_(is_gpu_host),
weak_factory_(this) {
- DCHECK(gpu_channel_manager);
- DCHECK(client_id);
+ DCHECK(gpu_channel_manager_);
+ DCHECK(client_id_);
- message_queue_ = new GpuChannelMessageQueue(this, task_runner, io_task_runner,
- preempting_flag, preempted_flag,
- sync_point_manager);
+ if (!scheduler_) {
+ message_queue_ = new GpuChannelMessageQueue(
+ this, sync_point_manager->CreateSyncPointOrderData(), task_runner,
+ io_task_runner, preempting_flag, preempted_flag);
+ }
- filter_ = new GpuChannelMessageFilter(this, message_queue_, task_runner);
+ filter_ =
+ new GpuChannelMessageFilter(this, scheduler, message_queue_, task_runner);
}
GpuChannel::~GpuChannel() {
@@ -602,7 +644,15 @@ GpuChannel::~GpuChannel() {
// Destroy filter first so that no message queue gets no more messages.
filter_->Destroy();
- message_queue_->Destroy();
+ // Release IPC channel. This acts like a flag for any posted tasks.
+ channel_ = nullptr;
+
+ if (scheduler_) {
+ for (const auto& kv : stream_sequences_)
+ scheduler_->DestroySequence(kv.second);
+ } else {
+ message_queue_->Destroy();
+ }
DCHECK(!preempting_flag_ || !preempting_flag_->IsSet());
}
@@ -656,13 +706,19 @@ bool GpuChannel::Send(IPC::Message* message) {
}
void GpuChannel::OnCommandBufferScheduled(GpuCommandBufferStub* stub) {
- message_queue_->SetScheduled(true);
- // TODO(sunnyps): Enable gpu scheduler task queue for stub's sequence.
+ if (scheduler_) {
+ scheduler_->EnableSequence(stub->sequence_id());
+ } else {
+ message_queue_->SetScheduled(true);
+ }
}
void GpuChannel::OnCommandBufferDescheduled(GpuCommandBufferStub* stub) {
- message_queue_->SetScheduled(false);
- // TODO(sunnyps): Disable gpu scheduler task queue for stub's sequence.
+ if (scheduler_) {
+ scheduler_->DisableSequence(stub->sequence_id());
+ } else {
+ message_queue_->SetScheduled(false);
+ }
}
GpuCommandBufferStub* GpuChannel::LookupCommandBuffer(int32_t route_id) {
@@ -685,11 +741,14 @@ void GpuChannel::MarkAllContextsLost() {
bool GpuChannel::AddRoute(int32_t route_id,
SequenceId sequence_id,
IPC::Listener* listener) {
- // TODO(sunnyps): Add route id to sequence id mapping to filter.
+ if (scheduler_)
+ filter_->AddRoute(route_id, sequence_id);
return router_.AddRoute(route_id, listener);
}
void GpuChannel::RemoveRoute(int32_t route_id) {
+ if (scheduler_)
+ filter_->RemoveRoute(route_id);
router_.RemoveRoute(route_id);
}
@@ -707,6 +766,38 @@ bool GpuChannel::OnControlMessageReceived(const IPC::Message& msg) {
return handled;
}
+void GpuChannel::HandleMessage(const IPC::Message& msg) {
+ // Even if we're in the process of being destroyed, be sure to reply to sync
+ // messages.
+ if (!channel_) {
+ if (msg.is_sync()) {
+ IPC::Message* reply = IPC::SyncMessage::GenerateReply(&msg);
+ reply->set_reply_error();
+ Send(reply);
piman 2017/05/09 00:48:38 nit: if channel_ is nullptr, Send won't do anythin
sunnyps 2017/05/10 23:15:15 Done.
+ }
+ return;
+ }
+
+ int32_t routing_id = msg.routing_id();
+ GpuCommandBufferStub* stub = LookupCommandBuffer(routing_id);
+
+ DCHECK(!stub || stub->IsScheduled());
+
+ DVLOG(1) << "received message @" << &msg << " on channel @" << this
+ << " with type " << msg.type();
+
+ HandleMessageHelper(msg);
+
+ // If we get descheduled or yield while processing a message.
+ if (stub && (stub->HasUnprocessedCommands() || !stub->IsScheduled())) {
+ DCHECK((uint32_t)GpuCommandBufferMsg_AsyncFlush::ID == msg.type() ||
+ (uint32_t)GpuCommandBufferMsg_WaitSyncToken::ID == msg.type());
+ scheduler_->ContinueTask(
+ stub->sequence_id(),
+ base::BindOnce(&GpuChannel::HandleMessage, AsWeakPtr(), msg));
+ }
+}
+
void GpuChannel::HandleMessageOnQueue() {
const GpuChannelMessage* channel_msg =
message_queue_->BeginMessageProcessing();
@@ -799,7 +890,7 @@ std::unique_ptr<GpuCommandBufferStub> GpuChannel::CreateCommandBuffer(
std::unique_ptr<base::SharedMemory> shared_state_shm) {
if (init_params.surface_handle != kNullSurfaceHandle && !is_gpu_host_) {
DLOG(ERROR) << "GpuChannel::CreateCommandBuffer(): attempt to create a "
- "view context on a non-priviledged channel";
+ "view context on a non-privileged channel";
return nullptr;
}
@@ -819,9 +910,9 @@ std::unique_ptr<GpuCommandBufferStub> GpuChannel::CreateCommandBuffer(
}
GpuStreamPriority stream_priority = init_params.stream_priority;
- if (stream_priority == GpuStreamPriority::REAL_TIME && !is_gpu_host_) {
- DLOG(ERROR) << "GpuChannel::CreateCommandBuffer(): real time stream "
- "priority not allowed";
+ if (stream_priority <= GpuStreamPriority::HIGH && !is_gpu_host_) {
+ DLOG(ERROR) << "GpuChannel::CreateCommandBuffer(): high priority stream "
+ "not allowed on a non-privileged channel";
return nullptr;
}
@@ -842,8 +933,16 @@ std::unique_ptr<GpuCommandBufferStub> GpuChannel::CreateCommandBuffer(
CommandBufferId command_buffer_id =
GenerateCommandBufferId(client_id_, route_id);
- // TODO(sunnyps): Lookup sequence id using stream id to sequence id map.
- SequenceId sequence_id = message_queue_->sequence_id();
+ SequenceId sequence_id;
+ if (scheduler_) {
+ sequence_id = stream_sequences_[stream_id];
+ if (sequence_id.is_null()) {
+ sequence_id = scheduler_->CreateSequence(stream_priority);
+ stream_sequences_[stream_id] = sequence_id;
+ }
+ } else {
+ sequence_id = message_queue_->sequence_id();
+ }
std::unique_ptr<GpuCommandBufferStub> stub(GpuCommandBufferStub::Create(
this, share_group, init_params, command_buffer_id, sequence_id, stream_id,

Powered by Google App Engine
This is Rietveld 408576698