// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gpu/command_buffer/service/task_graph.h"

#include <algorithm>
#include <utility>
#include <vector>

#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "base/synchronization/lock.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/time.h"

namespace gpu {
namespace {

void UpdateReleaseCount(
    base::flat_map<SyncPointClientId, uint64_t>* release_map,
    const SyncPointClientId& client_id,
    uint64_t release) {
  auto iter = release_map->find(client_id);
  if (iter == release_map->end()) {
    release_map->insert({client_id, release});
  } else if (iter->second < release) {
    iter->second = release;
  }
}

}  // namespace

FenceSyncReleaseDelegate::FenceSyncReleaseDelegate(
    SyncPointManager* sync_point_manager)
    : sync_point_manager_(sync_point_manager) {}

void FenceSyncReleaseDelegate::Release() {
  sync_point_manager_->EnsureFenceSyncReleased(
      release_upperbound_, ReleaseCause::kExplicitClientRelease);
}

void FenceSyncReleaseDelegate::Release(uint64_t release) {
  if (release > release_upperbound_.release_count()) {
    LOG(DFATAL) << "Attempt to release fence sync with a release count larger "
                   "than what was specified at task registration. Requested: "
                << release
                << "; registered: " << release_upperbound_.release_count();
    release = release_upperbound_.release_count();
  }

  SyncToken request(release_upperbound_.namespace_id(),
                    release_upperbound_.command_buffer_id(), release);
  sync_point_manager_->EnsureFenceSyncReleased(
      request, ReleaseCause::kExplicitClientRelease);
}

void FenceSyncReleaseDelegate::Reset(const SyncToken& release_upperbound) {
  release_upperbound_ = release_upperbound;
}

ScopedSyncPointClientState::ScopedSyncPointClientState(
    TaskGraph* task_graph,
    SequenceId sequence_id,
    CommandBufferNamespace namespace_id,
    CommandBufferId command_buffer_id)
    : task_graph_(task_graph),
      sequence_id_(sequence_id),
      namespace_id_(namespace_id),
      command_buffer_id_(command_buffer_id) {}

ScopedSyncPointClientState::~ScopedSyncPointClientState() {
  Reset();
}

ScopedSyncPointClientState::ScopedSyncPointClientState(
    ScopedSyncPointClientState&& other)
    : task_graph_(other.task_graph_),
      sequence_id_(other.sequence_id_),
      namespace_id_(other.namespace_id_),
      command_buffer_id_(other.command_buffer_id_) {
  other.task_graph_ = nullptr;
}

ScopedSyncPointClientState& ScopedSyncPointClientState::operator=(
    ScopedSyncPointClientState&& other) {
  if (&other != this) {
    task_graph_ = other.task_graph_;
    other.task_graph_ = nullptr;
    sequence_id_ = other.sequence_id_;
    namespace_id_ = other.namespace_id_;
    command_buffer_id_ = other.command_buffer_id_;
  }
  return *this;
}

void ScopedSyncPointClientState::Reset() {
  if (!task_graph_) {
    return;
  }

  task_graph_->DestroySyncPointClientState(sequence_id_, namespace_id_,
                                           command_buffer_id_);
  task_graph_ = nullptr;
}

TaskGraph::Sequence::Task::Task(base::OnceClosure task_closure,
                                uint32_t order_num,
                                const SyncToken& release,
                                ReportingCallback report_callback)
    : task_closure(std::move(task_closure)),
      order_num(order_num),
      release(release),
      report_callback(std::move(report_callback)) {}

TaskGraph::Sequence::Task::Task(Task&& other) = default;
TaskGraph::Sequence::Task::~Task() {
  CHECK(report_callback.is_null());
}

TaskGraph::Sequence::Task& TaskGraph::Sequence::Task::operator=(Task&& other) =
    default;

TaskGraph::Sequence::WaitFence::WaitFence(const SyncToken& sync_token,
                                          uint32_t order_num,
                                          SequenceId release_sequence_id)
    : sync_token(sync_token),
      order_num(order_num),
      release_sequence_id(release_sequence_id) {}
TaskGraph::Sequence::WaitFence::WaitFence(WaitFence&& other) = default;
TaskGraph::Sequence::WaitFence::~WaitFence() = default;
TaskGraph::Sequence::WaitFence& TaskGraph::Sequence::WaitFence::operator=(
    WaitFence&& other) = default;

TaskGraph::Sequence::Sequence(
    TaskGraph* task_graph,
    scoped_refptr<base::SingleThreadTaskRunner> validation_runner,
    CommandBufferNamespace namespace_id,
    CommandBufferId command_buffer_id)
    : task_graph_(task_graph),
      order_data_(task_graph_->sync_point_manager_->CreateSyncPointOrderData()),
      sequence_id_(order_data_->sequence_id()),
      release_delegate_(task_graph->sync_point_manager()) {
  if (task_graph_->graph_validation_enabled() && validation_runner) {
    validation_timer_ = base::MakeRefCounted<RetainingOneShotTimerHolder>(
        kMaxValidationDelay, kMinValidationDelay, std::move(validation_runner),
        base::BindRepeating(&TaskGraph::ValidateSequenceTaskFenceDeps,
                            base::Unretained(task_graph),
                            base::Unretained(this)));
  }

  if (namespace_id != CommandBufferNamespace::INVALID) {
    sync_point_states_.push_back(
        task_graph_->sync_point_manager()->CreateSyncPointClientState(
            namespace_id, command_buffer_id, sequence_id_));
  }
}

TaskGraph::Sequence::~Sequence() {
}

ScopedSyncPointClientState TaskGraph::Sequence::CreateSyncPointClientState(
    CommandBufferNamespace namespace_id,
    CommandBufferId command_buffer_id) {
  sync_point_states_.push_back(
      task_graph_->sync_point_manager()->CreateSyncPointClientState(
          namespace_id, command_buffer_id, sequence_id_));
  return ScopedSyncPointClientState(task_graph_, sequence_id_, namespace_id,
                                    command_buffer_id);
}

uint32_t TaskGraph::Sequence::AddTask(TaskCallback task_callback,
                                      std::vector<SyncToken> wait_fences,
                                      const SyncToken& release,
                                      ReportingCallback report_callback) {
  return AddTask(CreateTaskClosure(std::move(task_callback)),
                 std::move(wait_fences), release, std::move(report_callback));
}

uint32_t TaskGraph::Sequence::AddTask(base::OnceClosure task_closure,
                                      std::vector<SyncToken> wait_fences,
                                      const SyncToken& release,
                                      ReportingCallback report_callback) {
  const uint32_t order_num = order_data_->GenerateUnprocessedOrderNumber();
  tasks_.push_back({std::move(task_closure), order_num, release,
                    std::move(report_callback)});

  for (const SyncToken& sync_token : ReduceSyncTokens(wait_fences)) {
    SequenceId release_sequence_id =
        task_graph_->sync_point_manager_->GetSyncTokenReleaseSequenceId(
            sync_token);
    // base::Unretained is safe here since all sequences and corresponding sync
    // point callbacks will be released before the task graph is destroyed (even
    // though sync point manager itself outlives the task graph briefly).
    auto release_callback = base::BindOnce(
        &TaskGraph::SyncTokenFenceReleased, base::Unretained(task_graph_),
        sync_token, order_num, release_sequence_id, sequence_id_);
    // Only wait if we're not already waiting on the same sync token for the
    // same order number.
    auto it = wait_fences_.find(
        WaitFence{sync_token, order_num, release_sequence_id});
    if (it == wait_fences_.end() &&
        task_graph_->sync_point_manager_->Wait(
            sync_token, sequence_id_, order_num, std::move(release_callback))) {
      wait_fences_.emplace(sync_token, order_num, release_sequence_id);
      SetLastTaskFirstDependencyTimeIfNeeded();
    }
  }

  if (tasks_.size() == 1) {
    // The queue just got the first element, update the timer if necessary.
    UpdateValidationTimer();
  }

  return order_num;
}

uint32_t TaskGraph::Sequence::BeginTask(base::OnceClosure* task_closure) {
  DCHECK(task_closure);
  DCHECK(!tasks_.empty());

  DVLOG(10) << "Sequence " << sequence_id() << " is now running.";
  *task_closure = std::move(tasks_.front().task_closure);
  uint32_t order_num = tasks_.front().order_num;
  current_task_release_ = tasks_.front().release;
  release_delegate_.Reset(current_task_release_);

  if (!tasks_.front().report_callback.is_null()) {
    std::move(tasks_.front().report_callback).Run(tasks_.front().running_ready);
  }
  tasks_.pop_front();

  return order_num;
}

void TaskGraph::Sequence::FinishTask() {
  DVLOG(10) << "Sequence " << sequence_id() << " is now ending.";
  SyncToken release = current_task_release_;
  current_task_release_.Clear();
  UpdateValidationTimer();
}

void TaskGraph::Sequence::ContinueTask(TaskCallback task_callback) {
  ContinueTask(CreateTaskClosure(std::move(task_callback)));
}

void TaskGraph::Sequence::ContinueTask(base::OnceClosure task_closure) {
  const uint32_t order_num = order_data_->current_order_num();
  tasks_.push_front({std::move(task_closure), order_num, current_task_release_,
                     ReportingCallback()});
  current_task_release_.Clear();
  order_data_->PauseProcessingOrderNumber(order_num);
}

void TaskGraph::Sequence::SetLastTaskFirstDependencyTimeIfNeeded() {
  DCHECK(!tasks_.empty());
  if (tasks_.back().first_dependency_added.is_null()) {
    // Fence are always added for the last task (which should always exists).
    tasks_.back().first_dependency_added = base::TimeTicks::Now();
  }
}

base::TimeDelta TaskGraph::Sequence::FrontTaskWaitingDependencyDelta() {
  DCHECK(!tasks_.empty());
  if (tasks_.front().first_dependency_added.is_null()) {
    // didn't wait for dependencies.
    return base::TimeDelta();
  }
  return tasks_.front().running_ready - tasks_.front().first_dependency_added;
}

base::TimeDelta TaskGraph::Sequence::FrontTaskSchedulingDelay() {
  DCHECK(!tasks_.empty());
  return base::TimeTicks::Now() - tasks_.front().running_ready;
}

void TaskGraph::Sequence::RemoveWaitFence(const SyncToken& sync_token,
                                          uint32_t order_num,
                                          SequenceId release_sequence_id) {
  DVLOG(10) << "Sequence " << sequence_id_.value()
            << " removing wait fence that was released by sequence "
            << release_sequence_id.value() << ".";
  auto it =
      wait_fences_.find(WaitFence{sync_token, order_num, release_sequence_id});
  if (it == wait_fences_.end()) {
    return;
  }

  wait_fences_.erase(it);
  for (auto& task : tasks_) {
    if (order_num == task.order_num) {
      // The fence applies to this task, bump the readiness timestamp.
      task.running_ready = base::TimeTicks::Now();
      break;
    } else if (order_num < task.order_num) {
      // Updated all task related to this fence.
      break;
    }
  }

  DCHECK(!tasks_.empty());
  if (order_num == tasks_.front().order_num && IsFrontTaskUnblocked()) {
    OnFrontTaskUnblocked(order_num);
  }
}

bool TaskGraph::Sequence::IsFrontTaskUnblocked() const {
  return !tasks_.empty() &&
         (wait_fences_.empty() ||
          wait_fences_.begin()->order_num > tasks_.front().order_num);
}

void TaskGraph::Sequence::Destroy() {
  std::vector<scoped_refptr<SyncPointClientState>> sync_point_states;
  base::circular_deque<Task> tasks;
  {
    base::AutoLock auto_lock(task_graph_->lock());
    sync_point_states_.swap(sync_point_states);
    tasks_.swap(tasks);
  }

  if (validation_timer_) {
    validation_timer_->DestroyTimer();
  }

  for (auto& state : sync_point_states) {
    state->Destroy();
  }

  order_data_->Destroy();
}

scoped_refptr<SyncPointClientState>
TaskGraph::Sequence::TakeSyncPointClientState(
    CommandBufferNamespace namespace_id,
    CommandBufferId command_buffer_id) {
  scoped_refptr<SyncPointClientState> sync_point_state;
  for (auto iter = sync_point_states_.begin(); iter != sync_point_states_.end();
       ++iter) {
    if ((*iter)->namespace_id() == namespace_id &&
        (*iter)->command_buffer_id() == command_buffer_id) {
      sync_point_state = std::move(*iter);
      sync_point_states_.erase(iter);
      break;
    }
  }

  return sync_point_state;
}

void TaskGraph::Sequence::UpdateValidationTimer() {
  if (!validation_timer_ || !HasTasks()) {
    return;
  }

  validation_timer_->ResetTimerIfNecessary();
}

std::pair<TaskGraph::Sequence::WaitFenceConstIter,
          TaskGraph::Sequence::WaitFenceConstIter>
TaskGraph::Sequence::GetTaskWaitFences(const Task& task) const {
  struct Comp {
    bool operator()(const WaitFence& left, uint32_t right) {
      return left.order_num < right;
    }
    bool operator()(uint32_t left, const WaitFence& right) {
      return left < right.order_num;
    }
  };
  return std::equal_range(wait_fences_.begin(), wait_fences_.end(),
                          task.order_num, Comp{});
}

const TaskGraph::Sequence::Task* TaskGraph::Sequence::FindReleaseTask(
    const SyncToken& sync_token) const {
  for (const auto& task : tasks_) {
    if (task.release.HasData() &&
        task.release.namespace_id() == sync_token.namespace_id() &&
        task.release.command_buffer_id() == sync_token.command_buffer_id() &&
        task.release.release_count() >= sync_token.release_count()) {
      return &task;
    }
  }
  return nullptr;
}

base::OnceClosure TaskGraph::Sequence::CreateTaskClosure(
    TaskCallback task_callback) {
  return base::BindOnce(std::move(task_callback),
                        base::Unretained(&release_delegate_));
}
TaskGraph::TaskGraph(SyncPointManager* sync_point_manager)
    : sync_point_manager_(sync_point_manager) {}

TaskGraph::~TaskGraph() {
  base::AutoLock auto_lock(lock_);
  DCHECK(sequence_map_.empty());
}

void TaskGraph::AddSequence(std::unique_ptr<Sequence> sequence) {
  base::AutoLock auto_lock(lock_);
  SequenceId id = sequence->sequence_id();
  sequence_map_.emplace(id, std::move(sequence));
}

ScopedSyncPointClientState TaskGraph::CreateSyncPointClientState(
    SequenceId sequence_id,
    CommandBufferNamespace namespace_id,
    CommandBufferId command_buffer_id) {
  base::AutoLock auto_lock(lock_);
  auto* sequence = GetSequence(sequence_id);
  CHECK(sequence);
  return sequence->CreateSyncPointClientState(namespace_id, command_buffer_id);
}

void TaskGraph::DestroySequence(SequenceId sequence_id) {
  base::AutoLock auto_lock(lock_);
  std::unique_ptr<Sequence> sequence;

  // We want to destroy the sequence after removing it from the sequence map
  // so that looping over the sequence map does not access a destroyed
  // sequence.
  sequence = std::move(sequence_map_.at(sequence_id));
  CHECK(sequence);
  sequence_map_.erase(sequence_id);

  {
    // Thread annotation macros don't recognize base::AutoUnlock.
    lock_.Release();
    sequence->Destroy();
    lock_.Acquire();
  }
}

TaskGraph::Sequence* TaskGraph::GetSequence(SequenceId sequence_id) {
  auto it = sequence_map_.find(sequence_id);
  if (it != sequence_map_.end()) {
    return it->second.get();
  }
  return nullptr;
}

void TaskGraph::SyncTokenFenceReleased(const SyncToken& sync_token,
                                       uint32_t order_num,
                                       SequenceId release_sequence_id,
                                       SequenceId waiting_sequence_id) {
  base::AutoLock auto_lock(lock_);
  if (auto* sequence = GetSequence(waiting_sequence_id)) {
    sequence->RemoveWaitFence(sync_token, order_num, release_sequence_id);
  }
}

void TaskGraph::DestroySyncPointClientState(SequenceId sequence_id,
                                            CommandBufferNamespace namespace_id,
                                            CommandBufferId command_buffer_id) {
  scoped_refptr<SyncPointClientState> sync_point_client_state;
  {
    base::AutoLock auto_lock(lock_);
    Sequence* sequence = GetSequence(sequence_id);

    if (sequence) {
      sync_point_client_state =
          sequence->TakeSyncPointClientState(namespace_id, command_buffer_id);
    }
  }

  if (sync_point_client_state) {
    sync_point_client_state->Destroy();
  }
}

void TaskGraph::ValidateSequenceTaskFenceDeps(Sequence* root_sequence) {
  DCHECK(graph_validation_enabled());

  DVLOG(10) << "Validation: root sequence " << root_sequence->sequence_id();

  base::TimeTicks start_time = base::TimeTicks::Now();

  // Releases that need to be forcefully done to avoid invalid waits.
  ReleaseMap force_releases;
  {
    base::AutoLock auto_lock(lock_);

    if (!root_sequence->HasTasks()) {
      // Return without updating the timer. When the sequence becomes non-empty,
      // or after finishing the ongoing task, the validation timer will be
      // reset as needed.
      return;
    }

    // Releases that are supposed to happen once the validated tasks are
    // executed.
    ReleaseMap pending_releases;

    ValidateStateMap validate_states;

    base::TimeTicks now = base::TimeTicks::Now();
    for (Sequence::TaskIter task_iter = root_sequence->tasks_.begin();
         task_iter != root_sequence->tasks_.end(); ++task_iter) {
      if (now - task_iter->registration <= kMinValidationDelay) {
        break;
      }
      if (task_iter->validated) {
        continue;
      }

      ValidateTaskFenceDeps(root_sequence, task_iter, &pending_releases,
                            &force_releases, &validate_states);
    }
  }

  base::UmaHistogramBoolean("GPU.GraphValidation.NeedsForceRelease",
                            !force_releases.empty());

  for (const auto& [client_id, release] : force_releases) {
    sync_point_manager_->EnsureFenceSyncReleased(
        {client_id.namespace_id, client_id.command_buffer_id, release},
        ReleaseCause::kForceRelease);
  }

  base::UmaHistogramCustomTimes("GPU.GraphValidation.Duration",
                                base::TimeTicks::Now() - start_time,
                                base::Milliseconds(1), base::Seconds(1), 50);
}

void TaskGraph::ValidateTaskFenceDeps(
    Sequence* sequence,
    TaskGraph::Sequence::TaskIter task_iter,
    TaskGraph::ReleaseMap* pending_releases,
    TaskGraph::ReleaseMap* force_releases,
    TaskGraph::ValidateStateMap* validate_states) {
  Sequence::Task& task = *task_iter;

  auto& validate_state =
      GetSequenceValidateState(validate_states, pending_releases, sequence);
  CHECK(validate_state.next_to_validate == task_iter);
  CHECK(!validate_state.validating);

  validate_state.validating = true;

  DVLOG(10) << "Validation: sequence " << sequence->sequence_id() << "; task "
            << task.order_num;

  auto [fence_begin, fence_end] = sequence->GetTaskWaitFences(task);

  for (auto fence_iter = fence_begin; fence_iter != fence_end; ++fence_iter) {
    const Sequence::WaitFence& fence = *fence_iter;
    const SyncPointClientId client_id = fence.sync_token.GetClientId();

    Sequence* release_sequence = GetSequence(fence.release_sequence_id);
    ValidateState* release_validate_state = nullptr;

    // `release_sequence` is nullptr if the release sequence has been destroyed
    // and the corresponding wait fences hasn't been removed from other
    // sequences. The task graph lock is unlocked between the two operations, so
    // it is possible that validation happens right in the middle.
    if (release_sequence) {
      release_validate_state = &GetSequenceValidateState(
          validate_states, pending_releases, release_sequence);
    }

    // This should happen after the GetSequenceValidateState() call above, which
    // ensures that `pending_releases` has been updated for `release_sequence`.
    // Please see comments of GetSequenceValidateState().
    auto pending_release_iter = pending_releases->find(client_id);
    if (pending_release_iter != pending_releases->end() &&
        pending_release_iter->second >= fence.sync_token.release_count()) {
      continue;
    }

    const Sequence::Task* release_task =
        release_sequence ? release_sequence->FindReleaseTask(fence.sync_token)
                         : nullptr;

    if (!release_task) {
      // Null `release_task` indicates the wait-without-release case: A wait
      // fence is waited on for some time, but the release hasn't been
      // registered.
      // Forcefully release the fence.
      UpdateReleaseCount(pending_releases, client_id,
                         fence.sync_token.release_count());
      UpdateReleaseCount(force_releases, client_id,
                         fence.sync_token.release_count());

      LOG(ERROR) << "Validation: wait-without-release detected. Forcefully "
                    "release fence: Release sequence "
                 << fence.release_sequence_id << "; sync token "
                 << fence.sync_token.ToDebugString();
    } else {
      DCHECK(release_sequence);
      DCHECK(release_validate_state);

      if (release_validate_state->validating) {
        // Circular dependency detected.
        // Forcefully release the fence to break the cycle.
        UpdateReleaseCount(pending_releases, client_id,
                           fence.sync_token.release_count());
        UpdateReleaseCount(force_releases, client_id,
                           fence.sync_token.release_count());

        LOG(ERROR) << "Validation: cycle detected. Forcefully release fence: "
                      "release sequence "
                   << release_sequence->sequence_id() << "; sync token "
                   << fence.sync_token.ToDebugString();
      } else {
        // In order for `release_task` to get a chance to run, all prior tasks
        // in the same sequence must be able to run, so validate them all.
        for (auto dep_task_iter = release_validate_state->next_to_validate;
             dep_task_iter != release_sequence->tasks_.end(); ++dep_task_iter) {
          if (dep_task_iter->order_num > release_task->order_num) {
            break;
          }
          ValidateTaskFenceDeps(release_sequence, dep_task_iter,
                                pending_releases, force_releases,
                                validate_states);
        }
      }
    }
  }

  if (task.release.HasData()) {
    UpdateReleaseCount(pending_releases, task.release.GetClientId(),
                       task.release.release_count());
  }
  task.validated = true;

  validate_state.validating = false;
  validate_state.next_to_validate = std::next(task_iter);
}

TaskGraph::ValidateState& TaskGraph::GetSequenceValidateState(
    TaskGraph::ValidateStateMap* validate_states,
    ReleaseMap* pending_releases,
    Sequence* sequence) {
  auto state_iter = validate_states->find(sequence->sequence_id());
  if (state_iter != validate_states->end()) {
    return state_iter->second;
  }

  auto& validate_state = (*validate_states)[sequence->sequence_id()];

  // If there is a currently ongoing task, add its release to
  // `pending_releases`.
  auto& current_task_release = sequence->current_task_release_;
  if (current_task_release.HasData()) {
    UpdateReleaseCount(pending_releases, current_task_release.GetClientId(),
                       current_task_release.release_count());
  }

  validate_state.next_to_validate = sequence->tasks_.end();
  for (auto task_iter = sequence->tasks_.begin();
       task_iter != sequence->tasks_.end(); ++task_iter) {
    if (!task_iter->validated) {
      validate_state.next_to_validate = task_iter;
      break;
    }

    // If the task has been validated before, its release is considered
    // satisfiable and therefore directly added to `pending_releases`.
    if (task_iter->release.HasData()) {
      UpdateReleaseCount(pending_releases, task_iter->release.GetClientId(),
                         task_iter->release.release_count());
    }
  }

  return validate_state;
}

}  // namespace gpu
