blob: 4aa3c708b85c97c09b970d4545961af2475d8683 [file] [log] [blame]
// Copyright (c) 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef GPU_COMMAND_BUFFER_SERVICE_SCHEDULER_H_
#define GPU_COMMAND_BUFFER_SERVICE_SCHEDULER_H_
#include <queue>
#include <vector>
#include "base/callback.h"
#include "base/containers/flat_map.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
#include "gpu/command_buffer/common/scheduling_priority.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 trace_event {
class ConvertableToTraceFormat;
}
}
namespace gpu {
class SyncPointManager;
class GPU_EXPORT Scheduler {
public:
Scheduler(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
SyncPointManager* sync_point_manager);
virtual ~Scheduler();
// Create a sequence with given priority. Returns an identifier for the
// sequence that can be used with SyncPonintManager for creating sync point
// release clients. Sequences start off as enabled (see |EnableSequence|).
SequenceId CreateSequence(SchedulingPriority priority);
// Destroy the sequence and run any scheduled tasks immediately.
void DestroySequence(SequenceId sequence_id);
// Enables the sequence so that its tasks may be scheduled.
void EnableSequence(SequenceId sequence_id);
// Disables the sequence.
void DisableSequence(SequenceId sequence_id);
// Schedules task (closure) to run on the sequence. The task is blocked until
// the sync token fences are released or determined to be invalid. Tasks are
// run in the order in which they are submitted.
void ScheduleTask(SequenceId sequence_id,
base::OnceClosure closure,
const std::vector<SyncToken>& sync_token_fences);
// Continue running task on the sequence with the closure. This must be called
// while running a previously scheduled task.
void ContinueTask(SequenceId sequence_id, base::OnceClosure closure);
// If the sequence should yield so that a higher priority sequence may run.
bool ShouldYield(SequenceId sequence_id);
private:
class Sequence;
struct SchedulingState {
static bool Comparator(const SchedulingState& lhs,
const SchedulingState& rhs) {
return rhs.RunsBefore(lhs);
}
SchedulingState();
SchedulingState(const SchedulingState& other);
~SchedulingState();
bool RunsBefore(const SchedulingState& other) const {
return std::tie(priority, order_num) <
std::tie(other.priority, other.order_num);
}
std::unique_ptr<base::trace_event::ConvertableToTraceFormat> AsValue()
const;
SequenceId sequence_id;
SchedulingPriority priority = SchedulingPriority::kLowest;
uint32_t order_num = 0;
};
void SyncTokenFenceReleased(const SyncToken& sync_token,
uint32_t order_num,
SequenceId release_sequence_id,
SequenceId waiting_sequence_id);
void TryScheduleSequence(Sequence* sequence);
void RebuildSchedulingQueue();
Sequence* GetSequence(SequenceId sequence_id);
void RunNextTask();
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
SyncPointManager* const sync_point_manager_;
mutable base::Lock lock_;
// The following are protected by |lock_|.
bool running_ = false;
base::flat_map<SequenceId, std::unique_ptr<Sequence>> sequences_;
// Used as a priority queue for scheduling sequences. Min heap of
// SchedulingState with highest priority (lowest order) in front.
std::vector<SchedulingState> scheduling_queue_;
// If the scheduling queue needs to be rebuild because a sequence changed
// priority.
bool rebuild_scheduling_queue_ = false;
base::ThreadChecker thread_checker_;
base::WeakPtrFactory<Scheduler> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(Scheduler);
};
} // namespace gpu
#endif // GPU_COMMAND_BUFFER_SERVICE_SCHEDULER_H_