Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 1 | // Copyright 2022 The Chromium Authors |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #ifndef GPU_COMMAND_BUFFER_SERVICE_SCHEDULER_H_ |
| 6 | #define GPU_COMMAND_BUFFER_SERVICE_SCHEDULER_H_ |
| 7 | |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 8 | #include <vector> |
| 9 | |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 10 | #include "base/containers/flat_map.h" |
Victor Miura | 651b0c3 | 2017-11-18 05:03:43 | [diff] [blame] | 11 | #include "base/gtest_prod_util.h" |
Keishi Hattori | 0e45c02 | 2021-11-27 09:25:52 | [diff] [blame] | 12 | #include "base/memory/raw_ptr.h" |
François Doray | 5302033 | 2023-05-03 19:00:38 | [diff] [blame] | 13 | #include "base/rand_util.h" |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 14 | #include "base/synchronization/lock.h" |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 15 | #include "base/thread_annotations.h" |
Lucas Berthou | 8ab73ae | 2021-03-17 20:14:52 | [diff] [blame] | 16 | #include "base/time/time.h" |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 17 | #include "gpu/command_buffer/common/scheduling_priority.h" |
| 18 | #include "gpu/command_buffer/common/sync_token.h" |
Vasiliy Telezhnikov | f8bdccb | 2025-06-18 19:05:39 | [diff] [blame] | 19 | #include "gpu/command_buffer/service/gpu_command_buffer_service_export.h" |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 20 | #include "gpu/command_buffer/service/sequence_id.h" |
Yuzhu Shen | 52f3e2aa | 2024-06-18 17:35:45 | [diff] [blame] | 21 | #include "gpu/command_buffer/service/task_graph.h" |
Omar Elmekkawy | a2c0681 | 2021-12-09 18:13:47 | [diff] [blame] | 22 | #include "third_party/perfetto/include/perfetto/tracing/traced_value_forward.h" |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 23 | |
| 24 | namespace base { |
| 25 | class SingleThreadTaskRunner; |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 26 | } |
| 27 | |
| 28 | namespace gpu { |
Ramy El Garawany | b1dedd2 | 2022-12-06 02:32:50 | [diff] [blame] | 29 | |
Vasiliy Telezhnikov | f8bdccb | 2025-06-18 19:05:39 | [diff] [blame] | 30 | class GPU_COMMAND_BUFFER_SERVICE_EXPORT Scheduler { |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 31 | public: |
Vasiliy Telezhnikov | f8bdccb | 2025-06-18 19:05:39 | [diff] [blame] | 32 | struct GPU_COMMAND_BUFFER_SERVICE_EXPORT Task { |
Yuzhu Shen | ff6622c | 2024-08-29 21:18:44 | [diff] [blame] | 33 | // Use the signature with TaskCallback if the task needs to determine when |
| 34 | // to release fence sync during task execution. Please also see comments of |
| 35 | // TaskCallback. |
| 36 | // Use the signatures with base::OnceClosure if the task doesn't release |
| 37 | // fence sync, or the release can be done automatically after task |
| 38 | // execution. |
Sunny Sachanandani | 9b8fb34 | 2017-08-26 00:49:56 | [diff] [blame] | 39 | Task(SequenceId sequence_id, |
Yuzhu Shen | ff6622c | 2024-08-29 21:18:44 | [diff] [blame] | 40 | TaskCallback task_callback, |
Lucas Berthou | e2649ff | 2021-03-25 08:43:02 | [diff] [blame] | 41 | std::vector<SyncToken> sync_token_fences, |
Yuzhu Shen | 6a71fb8e | 2024-06-28 02:39:15 | [diff] [blame] | 42 | const SyncToken& release, |
Lucas Berthou | e2649ff | 2021-03-25 08:43:02 | [diff] [blame] | 43 | ReportingCallback report_callback = ReportingCallback()); |
Yuzhu Shen | 6a71fb8e | 2024-06-28 02:39:15 | [diff] [blame] | 44 | |
Yuzhu Shen | 6a71fb8e | 2024-06-28 02:39:15 | [diff] [blame] | 45 | Task(SequenceId sequence_id, |
Yuzhu Shen | ff6622c | 2024-08-29 21:18:44 | [diff] [blame] | 46 | base::OnceClosure task_closure, |
| 47 | std::vector<SyncToken> sync_token_fences, |
| 48 | const SyncToken& release, |
| 49 | ReportingCallback report_callback = ReportingCallback()); |
| 50 | |
| 51 | Task(SequenceId sequence_id, |
| 52 | base::OnceClosure task_closure, |
Yuzhu Shen | 6a71fb8e | 2024-06-28 02:39:15 | [diff] [blame] | 53 | std::vector<SyncToken> sync_token_fences, |
| 54 | ReportingCallback report_callback = ReportingCallback()); |
| 55 | |
Sunny Sachanandani | 9b8fb34 | 2017-08-26 00:49:56 | [diff] [blame] | 56 | Task(Task&& other); |
| 57 | ~Task(); |
| 58 | Task& operator=(Task&& other); |
| 59 | |
| 60 | SequenceId sequence_id; |
Yuzhu Shen | ff6622c | 2024-08-29 21:18:44 | [diff] [blame] | 61 | |
| 62 | // Only one of the two is used. |
| 63 | TaskCallback task_callback; |
| 64 | base::OnceClosure task_closure; |
| 65 | |
Sunny Sachanandani | 9b8fb34 | 2017-08-26 00:49:56 | [diff] [blame] | 66 | std::vector<SyncToken> sync_token_fences; |
Yuzhu Shen | 6a71fb8e | 2024-06-28 02:39:15 | [diff] [blame] | 67 | |
| 68 | // The release that is expected to be reached after execution of this task. |
Yuzhu Shen | 6a71fb8e | 2024-06-28 02:39:15 | [diff] [blame] | 69 | SyncToken release; |
| 70 | |
Lucas Berthou | e2649ff | 2021-03-25 08:43:02 | [diff] [blame] | 71 | ReportingCallback report_callback; |
Sunny Sachanandani | 9b8fb34 | 2017-08-26 00:49:56 | [diff] [blame] | 72 | }; |
| 73 | |
Vasiliy Telezhnikov | f8bdccb | 2025-06-18 19:05:39 | [diff] [blame] | 74 | struct GPU_COMMAND_BUFFER_SERVICE_EXPORT ScopedSetSequencePriority { |
Bo Liu | eca0009f | 2022-08-25 22:59:32 | [diff] [blame] | 75 | public: |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 76 | ScopedSetSequencePriority(Scheduler* scheduler, |
| 77 | SequenceId sequence_id, |
| 78 | SchedulingPriority priority); |
| 79 | ~ScopedSetSequencePriority(); |
Bo Liu | eca0009f | 2022-08-25 22:59:32 | [diff] [blame] | 80 | |
| 81 | private: |
| 82 | const raw_ptr<Scheduler> scheduler_; |
| 83 | const SequenceId sequence_id_; |
Bo Liu | eca0009f | 2022-08-25 22:59:32 | [diff] [blame] | 84 | }; |
| 85 | |
Maggie Chen | 0b4389c | 2024-08-07 21:25:05 | [diff] [blame] | 86 | explicit Scheduler(SyncPointManager* sync_point_manager); |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 87 | |
Peter BostrÃļm | dbacdc2 | 2021-09-23 22:11:46 | [diff] [blame] | 88 | Scheduler(const Scheduler&) = delete; |
| 89 | Scheduler& operator=(const Scheduler&) = delete; |
| 90 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 91 | ~Scheduler() LOCKS_EXCLUDED(lock()); |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 92 | |
| 93 | // Create a sequence with given priority. Returns an identifier for the |
Vikas Soni | 4fa4c09a | 2021-05-14 20:19:19 | [diff] [blame] | 94 | // sequence that can be used with SyncPointManager for creating sync point |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 95 | // release clients. Sequences start off as enabled (see |EnableSequence|). |
Vikas Soni | 1e0503e | 2021-06-04 01:29:03 | [diff] [blame] | 96 | // Sequence is bound to the provided |task_runner|. |
| 97 | SequenceId CreateSequence( |
| 98 | SchedulingPriority priority, |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 99 | scoped_refptr<base::SingleThreadTaskRunner> task_runner) |
| 100 | LOCKS_EXCLUDED(lock()); |
Vikas Soni | 1e0503e | 2021-06-04 01:29:03 | [diff] [blame] | 101 | |
Yuzhu Shen | 07b2217 | 2024-09-17 22:25:15 | [diff] [blame] | 102 | // Similar to the method above, but also creates a SyncPointClientState |
| 103 | // associated with the sequence. The SyncPointClientState object is destroyed |
| 104 | // when the sequence is destroyed. |
| 105 | SequenceId CreateSequence( |
| 106 | SchedulingPriority priority, |
| 107 | scoped_refptr<base::SingleThreadTaskRunner> task_runner, |
| 108 | CommandBufferNamespace namespace_id, |
| 109 | CommandBufferId command_buffer_id) LOCKS_EXCLUDED(lock()); |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 110 | |
Weiliang Chen | af34b93 | 2019-07-18 18:59:17 | [diff] [blame] | 111 | // Destroy the sequence and run any scheduled tasks immediately. Sequence |
| 112 | // could be destroyed outside of GPU thread. |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 113 | void DestroySequence(SequenceId sequence_id) LOCKS_EXCLUDED(lock()); |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 114 | |
Yuzhu Shen | 07b2217 | 2024-09-17 22:25:15 | [diff] [blame] | 115 | [[nodiscard]] ScopedSyncPointClientState CreateSyncPointClientState( |
| 116 | SequenceId sequence_id, |
| 117 | CommandBufferNamespace namespace_id, |
| 118 | CommandBufferId command_buffer_id) LOCKS_EXCLUDED(lock()); |
Yuzhu Shen | ff6622c | 2024-08-29 21:18:44 | [diff] [blame] | 119 | |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 120 | // Enables the sequence so that its tasks may be scheduled. |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 121 | void EnableSequence(SequenceId sequence_id) LOCKS_EXCLUDED(lock()); |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 122 | |
| 123 | // Disables the sequence. |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 124 | void DisableSequence(SequenceId sequence_id) LOCKS_EXCLUDED(lock()); |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 125 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 126 | // Gets the priority that the sequence was created with. |
| 127 | SchedulingPriority GetSequenceDefaultPriority(SequenceId sequence_id) |
| 128 | LOCKS_EXCLUDED(lock()); |
Sunny Sachanandani | c985967 | 2017-10-11 23:19:16 | [diff] [blame] | 129 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 130 | // Changes a sequence's priority. Used in WaitForGetOffset/TokenInRange to |
| 131 | // temporarily increase a sequence's priority. |
| 132 | void SetSequencePriority(SequenceId sequence_id, SchedulingPriority priority) |
| 133 | LOCKS_EXCLUDED(lock()); |
Sunny Sachanandani | c985967 | 2017-10-11 23:19:16 | [diff] [blame] | 134 | |
Yuzhu Shen | ff6622c | 2024-08-29 21:18:44 | [diff] [blame] | 135 | // Schedules task to run on the sequence. The task is blocked until the sync |
| 136 | // token fences are released or determined to be invalid. Tasks are run in the |
| 137 | // order in which they are submitted. |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 138 | void ScheduleTask(Scheduler::Task task) LOCKS_EXCLUDED(lock()); |
Sunny Sachanandani | 9b8fb34 | 2017-08-26 00:49:56 | [diff] [blame] | 139 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 140 | void ScheduleTasks(std::vector<Scheduler::Task> tasks) LOCKS_EXCLUDED(lock()); |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 141 | |
Yuzhu Shen | ff6622c | 2024-08-29 21:18:44 | [diff] [blame] | 142 | // Continue running task on the sequence with the callback. This must be |
| 143 | // called while running a previously scheduled task. |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 144 | void ContinueTask(SequenceId sequence_id, TaskCallback task_callback) |
| 145 | LOCKS_EXCLUDED(lock()); |
| 146 | void ContinueTask(SequenceId sequence_id, base::OnceClosure task_closure) |
| 147 | LOCKS_EXCLUDED(lock()); |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 148 | |
| 149 | // If the sequence should yield so that a higher priority sequence may run. |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 150 | bool ShouldYield(SequenceId sequence_id) LOCKS_EXCLUDED(lock()); |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 151 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 152 | base::SingleThreadTaskRunner* GetTaskRunnerForTesting(SequenceId sequence_id) |
| 153 | LOCKS_EXCLUDED(lock()); |
Minoru Chikamune | 5c81af1 | 2021-04-15 03:30:51 | [diff] [blame] | 154 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 155 | bool graph_validation_enabled() const { |
| 156 | return task_graph_.graph_validation_enabled(); |
| 157 | } |
Ramy El Garawany | b1dedd2 | 2022-12-06 02:32:50 | [diff] [blame] | 158 | |
Yuzhu Shen | 52f3e2aa | 2024-06-18 17:35:45 | [diff] [blame] | 159 | TaskGraph* task_graph() { return &task_graph_; } |
| 160 | |
Vikas Soni | 4fa4c09a | 2021-05-14 20:19:19 | [diff] [blame] | 161 | private: |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 162 | struct SchedulingState { |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 163 | SchedulingState(); |
| 164 | SchedulingState(const SchedulingState& other); |
| 165 | ~SchedulingState(); |
| 166 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 167 | static bool RunsBefore(const SchedulingState& lhs, |
| 168 | const SchedulingState& rhs) { |
| 169 | return std::tie(lhs.priority, lhs.order_num) < |
| 170 | std::tie(rhs.priority, rhs.order_num); |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 171 | } |
| 172 | |
Omar Elmekkawy | a2c0681 | 2021-12-09 18:13:47 | [diff] [blame] | 173 | void WriteIntoTrace(perfetto::TracedValue context) const; |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 174 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 175 | bool operator==(const SchedulingState& rhs) const; |
| 176 | |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 177 | SequenceId sequence_id; |
Sunny Sachanandani | c985967 | 2017-10-11 23:19:16 | [diff] [blame] | 178 | SchedulingPriority priority = SchedulingPriority::kLow; |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 179 | uint32_t order_num = 0; |
| 180 | }; |
| 181 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 182 | // All public methods except constructor must be accessed under TaskGraph's |
| 183 | // lock. Please see locking annotation of individual methods. |
Vasiliy Telezhnikov | f8bdccb | 2025-06-18 19:05:39 | [diff] [blame] | 184 | class GPU_COMMAND_BUFFER_SERVICE_EXPORT Sequence |
| 185 | : public TaskGraph::Sequence { |
Victor Miura | 651b0c3 | 2017-11-18 05:03:43 | [diff] [blame] | 186 | public: |
Yuzhu Shen | 07b2217 | 2024-09-17 22:25:15 | [diff] [blame] | 187 | Sequence( |
| 188 | Scheduler* scheduler, |
| 189 | scoped_refptr<base::SingleThreadTaskRunner> task_runner, |
| 190 | SchedulingPriority priority, |
| 191 | CommandBufferNamespace namespace_id = CommandBufferNamespace::INVALID, |
| 192 | CommandBufferId command_buffer_id = {}); |
Victor Miura | 651b0c3 | 2017-11-18 05:03:43 | [diff] [blame] | 193 | |
Peter BostrÃļm | dbacdc2 | 2021-09-23 22:11:46 | [diff] [blame] | 194 | Sequence(const Sequence&) = delete; |
| 195 | Sequence& operator=(const Sequence&) = delete; |
| 196 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 197 | ~Sequence() override EXCLUSIVE_LOCKS_REQUIRED(lock()); |
Victor Miura | 651b0c3 | 2017-11-18 05:03:43 | [diff] [blame] | 198 | |
Vikas Soni | 1e0503e | 2021-06-04 01:29:03 | [diff] [blame] | 199 | base::SingleThreadTaskRunner* task_runner() const { |
| 200 | return task_runner_.get(); |
| 201 | } |
Vikas Soni | 4fa4c09a | 2021-05-14 20:19:19 | [diff] [blame] | 202 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 203 | bool enabled() const EXCLUSIVE_LOCKS_REQUIRED(lock()) { return enabled_; } |
Victor Miura | 651b0c3 | 2017-11-18 05:03:43 | [diff] [blame] | 204 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 205 | bool scheduled() const EXCLUSIVE_LOCKS_REQUIRED(lock()) { |
| 206 | return running_state_ == SCHEDULED; |
| 207 | } |
Victor Miura | 651b0c3 | 2017-11-18 05:03:43 | [diff] [blame] | 208 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 209 | bool running() const EXCLUSIVE_LOCKS_REQUIRED(lock()) { |
| 210 | return running_state_ == RUNNING; |
| 211 | } |
Victor Miura | 651b0c3 | 2017-11-18 05:03:43 | [diff] [blame] | 212 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 213 | bool HasTasksAndEnabled() const EXCLUSIVE_LOCKS_REQUIRED(lock()) { |
| 214 | return enabled() && HasTasks(); |
| 215 | } |
Victor Miura | 651b0c3 | 2017-11-18 05:03:43 | [diff] [blame] | 216 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 217 | // A sequence is runnable if it is enabled, is not already running, and has |
| 218 | // tasks in its queue. Note that this does *not* necessarily mean that its |
| 219 | // first task unblocked. |
| 220 | bool IsRunnable() const EXCLUSIVE_LOCKS_REQUIRED(lock()) { |
| 221 | return enabled() && !running() && HasTasks(); |
| 222 | } |
Victor Miura | 651b0c3 | 2017-11-18 05:03:43 | [diff] [blame] | 223 | |
| 224 | // Returns true if this sequence should yield to another sequence. Uses the |
| 225 | // cached scheduling state for comparison. |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 226 | bool ShouldYieldTo(const Sequence* other) const |
| 227 | EXCLUSIVE_LOCKS_REQUIRED(lock()); |
Victor Miura | 651b0c3 | 2017-11-18 05:03:43 | [diff] [blame] | 228 | |
| 229 | // Enables or disables the sequence. |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 230 | void SetEnabled(bool enabled) EXCLUSIVE_LOCKS_REQUIRED(lock()); |
Victor Miura | 651b0c3 | 2017-11-18 05:03:43 | [diff] [blame] | 231 | |
| 232 | // Sets running state to SCHEDULED. Returns scheduling state for this |
| 233 | // sequence used for inserting in the scheduling queue. |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 234 | SchedulingState SetScheduled() EXCLUSIVE_LOCKS_REQUIRED(lock()); |
Victor Miura | 651b0c3 | 2017-11-18 05:03:43 | [diff] [blame] | 235 | |
| 236 | // Update cached scheduling priority while running. |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 237 | void UpdateRunningPriority() EXCLUSIVE_LOCKS_REQUIRED(lock()); |
Victor Miura | 651b0c3 | 2017-11-18 05:03:43 | [diff] [blame] | 238 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 239 | using TaskGraph::Sequence::AddTask; |
Lucas Berthou | 8ab73ae | 2021-03-17 20:14:52 | [diff] [blame] | 240 | |
Victor Miura | 651b0c3 | 2017-11-18 05:03:43 | [diff] [blame] | 241 | // Returns the next order number and closure. Sets running state to RUNNING. |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 242 | uint32_t BeginTask(base::OnceClosure* task_closure) override |
| 243 | EXCLUSIVE_LOCKS_REQUIRED(lock()); |
Victor Miura | 651b0c3 | 2017-11-18 05:03:43 | [diff] [blame] | 244 | |
| 245 | // Called after running the closure returned by BeginTask. Sets running |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 246 | // state to SCHEDULED. |
| 247 | void FinishTask() override EXCLUSIVE_LOCKS_REQUIRED(lock()); |
Victor Miura | 651b0c3 | 2017-11-18 05:03:43 | [diff] [blame] | 248 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 249 | using TaskGraph::Sequence::ContinueTask; |
Victor Miura | 651b0c3 | 2017-11-18 05:03:43 | [diff] [blame] | 250 | |
| 251 | // Continue running the current task with the given closure. Must be called |
| 252 | // in between |BeginTask| and |FinishTask|. |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 253 | void ContinueTask(base::OnceClosure task_closure) override |
| 254 | EXCLUSIVE_LOCKS_REQUIRED(lock()); |
Victor Miura | 651b0c3 | 2017-11-18 05:03:43 | [diff] [blame] | 255 | |
Sunny Sachanandani | 0eefabc | 2025-02-06 21:58:30 | [diff] [blame] | 256 | void OnFrontTaskUnblocked(uint32_t order_num) override |
| 257 | EXCLUSIVE_LOCKS_REQUIRED(lock()); |
| 258 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 259 | SchedulingPriority current_priority() const |
| 260 | EXCLUSIVE_LOCKS_REQUIRED(lock()) { |
| 261 | return current_priority_; |
Yuzhu Shen | ff6622c | 2024-08-29 21:18:44 | [diff] [blame] | 262 | } |
| 263 | |
Victor Miura | 651b0c3 | 2017-11-18 05:03:43 | [diff] [blame] | 264 | private: |
Bo Liu | 3bf6be5 | 2020-07-07 15:56:25 | [diff] [blame] | 265 | friend class Scheduler; |
| 266 | |
Victor Miura | 651b0c3 | 2017-11-18 05:03:43 | [diff] [blame] | 267 | enum RunningState { IDLE, SCHEDULED, RUNNING }; |
| 268 | |
Victor Miura | 651b0c3 | 2017-11-18 05:03:43 | [diff] [blame] | 269 | // If the sequence is enabled. Sequences are disabled/enabled based on when |
| 270 | // the command buffer is descheduled/scheduled. |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 271 | bool enabled_ GUARDED_BY(lock()) = true; |
Victor Miura | 651b0c3 | 2017-11-18 05:03:43 | [diff] [blame] | 272 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 273 | // TODO(elgarawany): This is no longer needed. Replace with bool running_. |
| 274 | RunningState running_state_ GUARDED_BY(lock()) = IDLE; |
Victor Miura | 651b0c3 | 2017-11-18 05:03:43 | [diff] [blame] | 275 | |
| 276 | // Cached scheduling state used for comparison with other sequences while |
| 277 | // running. Updated in |SetScheduled| and |UpdateRunningPriority|. |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 278 | SchedulingState scheduling_state_ GUARDED_BY(lock()); |
Victor Miura | 651b0c3 | 2017-11-18 05:03:43 | [diff] [blame] | 279 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 280 | // RAW_PTR_EXCLUSION: Scheduler was added to raw_ptr unsupported type for |
| 281 | // performance reasons. See raw_ptr.h for more info. |
| 282 | RAW_PTR_EXCLUSION Scheduler* const scheduler_ = nullptr; |
| 283 | const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
Victor Miura | 651b0c3 | 2017-11-18 05:03:43 | [diff] [blame] | 284 | |
| 285 | const SchedulingPriority default_priority_; |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 286 | SchedulingPriority current_priority_ GUARDED_BY(lock()); |
Victor Miura | 651b0c3 | 2017-11-18 05:03:43 | [diff] [blame] | 287 | }; |
| 288 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 289 | base::Lock& lock() const LOCK_RETURNED(task_graph_.lock()) { |
| 290 | return task_graph_.lock(); |
| 291 | } |
Bo Liu | eca0009f | 2022-08-25 22:59:32 | [diff] [blame] | 292 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 293 | Sequence* GetSequence(SequenceId sequence_id) |
| 294 | EXCLUSIVE_LOCKS_REQUIRED(lock()); |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 295 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 296 | void ScheduleTaskHelper(Scheduler::Task task) |
| 297 | EXCLUSIVE_LOCKS_REQUIRED(lock()); |
Sunny Sachanandani | 9b8fb34 | 2017-08-26 00:49:56 | [diff] [blame] | 298 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 299 | void TryScheduleSequence(Sequence* sequence) EXCLUSIVE_LOCKS_REQUIRED(lock()); |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 300 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 301 | // Returns a sorted list of runnable sequences. |
| 302 | const std::vector<SchedulingState>& GetSortedRunnableSequences( |
| 303 | base::SingleThreadTaskRunner* task_runner) |
| 304 | EXCLUSIVE_LOCKS_REQUIRED(lock()); |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 305 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 306 | // Returns true if there are *any* unblocked tasks in sequences assigned to |
| 307 | // |task_runner|. This is used to decide if RunNextTask needs to be |
| 308 | // rescheduled. |
| 309 | bool HasAnyUnblockedTasksOnRunner( |
| 310 | const base::SingleThreadTaskRunner* task_runner) const |
| 311 | EXCLUSIVE_LOCKS_REQUIRED(lock()); |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 312 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 313 | // Finds the sequence of the next task that can be run under |root_sequence|'s |
| 314 | // dependency graph. This function will visit sequences that are tied to other |
| 315 | // threads in case other threads depends on work on this thread; however, it |
| 316 | // will not run any *leaves* that are tied to other threads. nullptr is |
| 317 | // returned only if DrDC is enabled and when a sequence's only dependency is a |
| 318 | // sequence that is tied to another thread. |
| 319 | Sequence* FindNextTaskFromRoot(Sequence* root_sequence) |
| 320 | EXCLUSIVE_LOCKS_REQUIRED(lock()); |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 321 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 322 | // Calls |FindNextTaskFromRoot| on the ordered list of all sequences, and |
| 323 | // returns the first runnable task. Returns nullptr if there is no work to do. |
| 324 | Sequence* FindNextTask() EXCLUSIVE_LOCKS_REQUIRED(lock()); |
| 325 | |
| 326 | // Executes the closure of the first task for |sequence_id|. Assumes that |
| 327 | // the sequence has tasks, and that the first task is unblocked. |
| 328 | void ExecuteSequence(SequenceId sequence_id) LOCKS_EXCLUDED(lock()); |
| 329 | |
| 330 | // The scheduler's main loop. At each tick, it will call FindNextTask on the |
| 331 | // sorted list of sequences to find the highest priority available sequence. |
| 332 | // The scheduler then walks the sequence's dependency graph using DFS to find |
| 333 | // any unblocked task. If there are multiple choices at any node, the |
| 334 | // scheduler picks the dependency with the lowest SchedulingState, effectively |
| 335 | // ordering the dependencies by priority and order_num. |
| 336 | void RunNextTask() LOCKS_EXCLUDED(lock()); |
| 337 | |
| 338 | TaskGraph task_graph_; |
| 339 | |
| 340 | // The Sequence instances in the map are owned by `task_graph_`. |
| 341 | base::flat_map<SequenceId, Sequence*> scheduler_sequence_map_ |
| 342 | GUARDED_BY(lock()); |
| 343 | |
| 344 | base::MetricsSubSampler metrics_subsampler_ GUARDED_BY(lock()); |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 345 | |
Vikas Soni | 4fa4c09a | 2021-05-14 20:19:19 | [diff] [blame] | 346 | // Each thread will have its own priority queue to schedule sequences |
| 347 | // created on that thread. |
| 348 | struct PerThreadState { |
| 349 | PerThreadState(); |
| 350 | PerThreadState(PerThreadState&&); |
| 351 | ~PerThreadState(); |
| 352 | PerThreadState& operator=(PerThreadState&&); |
Sunny Sachanandani | f7c6409d | 2022-05-18 19:53:43 | [diff] [blame] | 353 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 354 | // Sorted list of SchedulingState that contains sequences that Runnable. Is |
| 355 | // only used so that GetSortedRunnableSequences does not have to re-allocate |
| 356 | // a vector. It is rebuilt at each call to GetSortedRunnableSequences. |
| 357 | std::vector<SchedulingState> sorted_sequences; |
Sunny Sachanandani | f7c6409d | 2022-05-18 19:53:43 | [diff] [blame] | 358 | |
| 359 | // Indicates if the scheduler is actively running tasks on this thread. |
Vikas Soni | 4fa4c09a | 2021-05-14 20:19:19 | [diff] [blame] | 360 | bool running = false; |
Sunny Sachanandani | f7c6409d | 2022-05-18 19:53:43 | [diff] [blame] | 361 | |
| 362 | // Indicates when the next task run was scheduled |
| 363 | base::TimeTicks run_next_task_scheduled; |
Vikas Soni | 4fa4c09a | 2021-05-14 20:19:19 | [diff] [blame] | 364 | }; |
Vikas Soni | 1e0503e | 2021-06-04 01:29:03 | [diff] [blame] | 365 | base::flat_map<base::SingleThreadTaskRunner*, PerThreadState> |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 366 | per_thread_state_map_ GUARDED_BY(lock()); |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 367 | |
Yuzhu Shen | 84ee857 | 2024-09-06 01:30:47 | [diff] [blame] | 368 | // Accumulated time the thread was blocked during running task |
| 369 | base::TimeDelta total_blocked_time_ GUARDED_BY(lock()); |
Ramy El Garawany | b1dedd2 | 2022-12-06 02:32:50 | [diff] [blame] | 370 | |
Victor Miura | 651b0c3 | 2017-11-18 05:03:43 | [diff] [blame] | 371 | private: |
| 372 | FRIEND_TEST_ALL_PREFIXES(SchedulerTest, StreamPriorities); |
sunnyps | 8f9139e | 2017-05-12 17:53:25 | [diff] [blame] | 373 | }; |
| 374 | |
| 375 | } // namespace gpu |
| 376 | |
| 377 | #endif // GPU_COMMAND_BUFFER_SERVICE_SCHEDULER_H_ |