blob: 79d0e1e0071887881af9d619f9b9c657cc6e4a04 [file]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/webnn/scoped_gpu_sequence.h"
#include "base/functional/callback_helpers.h"
#include "base/task/single_thread_task_runner.h"
#include "gpu/command_buffer/service/scheduler.h"
#include "gpu/command_buffer/service/scheduler_task_runner.h"
namespace webnn {
ScopedGpuSequence::ScopedGpuSequence(
gpu::Scheduler& scheduler,
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
gpu::CommandBufferId command_buffer_id,
gpu::CommandBufferNamespace namespace_id)
: scheduler_(scheduler),
command_buffer_id_(command_buffer_id),
namespace_id_(namespace_id),
sequence_id_(scheduler_->CreateSequence(gpu::SchedulingPriority::kNormal,
std::move(task_runner),
namespace_id_,
command_buffer_id_)),
scheduler_task_runner_(
base::MakeRefCounted<gpu::SchedulerTaskRunner>(*scheduler_,
sequence_id_)) {
// Detach so the checker binds to whichever thread first schedules a task.
DETACH_FROM_SEQUENCE(sequence_checker_);
}
ScopedGpuSequence::~ScopedGpuSequence() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// Note: ShutDown() prevents new tasks from being scheduled and drops existing
// ones from executing.
scheduler_task_runner_->ShutDown();
// Prevent pending scheduled tasks from running after DestroySequence() is
// called.
weak_factory_.InvalidateWeakPtrs();
scheduler_->DestroySequence(sequence_id_);
}
void ScopedGpuSequence::ScheduleGpuTask(base::OnceClosure task_closure,
gpu::SyncToken fence,
gpu::SyncToken release) {
ScheduleGpuTaskImpl(std::move(task_closure), {fence}, release);
}
void ScopedGpuSequence::ScheduleGpuTaskImpl(base::OnceClosure task_closure,
std::vector<gpu::SyncToken> fences,
const gpu::SyncToken& release) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::OnceClosure runnable_task = base::BindOnce(
[](base::WeakPtr<ScopedGpuSequence> self, base::OnceClosure task) {
// Tasks scheduled are wrapped in a WeakPtr check. If the sequence is
// destroyed, the task is skipped, but the SyncToken is still signaled
// by the scheduler to prevent deadlocks.
if (self) {
std::move(task).Run();
}
},
weak_factory_.GetWeakPtr(), std::move(task_closure));
scheduler_->ScheduleTask(gpu::Scheduler::Task(
sequence_id_, std::move(runnable_task), std::move(fences), release));
}
} // namespace webnn