// 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,
                                uint64_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,
                                          uint64_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() {
  task_graph_->UpdateConcurrencyMetrics(base::TimeTicks::Now());
  task_graph_->running_sequences_.erase(sequence_id_);
}

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);
}

uint64_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));
}

uint64_t TaskGraph::Sequence::AddTask(base::OnceClosure task_closure,
                                      std::vector<SyncToken> wait_fences,
                                      const SyncToken& release,
                                      ReportingCallback report_callback) {
  const uint64_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;
}

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

  base::TimeTicks now = base::TimeTicks::Now();
  task_graph_->UpdateConcurrencyMetrics(now);
  task_graph_->running_sequences_.insert(sequence_id_);

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

  current_task_start_time_ = now;
  current_task_concurrent_time_ = base::TimeDelta();

  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.";

  base::TimeTicks now = base::TimeTicks::Now();
  task_graph_->UpdateConcurrencyMetrics(now);
  task_graph_->running_sequences_.erase(sequence_id_);

  base::TimeDelta duration = now - current_task_start_time_;
  if (duration.is_positive()) {
    last_task_concurrency_ratio_ =
        current_task_concurrent_time_.InMicrosecondsF() /
        duration.InMicrosecondsF();
  } else {
    last_task_concurrency_ratio_ = 0;
  }

  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 uint64_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;
}

void TaskGraph::Sequence::RemoveWaitFence(const SyncToken& sync_token,
                                          uint64_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, uint64_t right) {
      return left.order_num < right;
    }
    bool operator()(uint64_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,
                                       uint64_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::UpdateConcurrencyMetrics(base::TimeTicks now) {
  if (!last_concurrency_update_time_.is_null()) {
    base::TimeDelta delta = now - last_concurrency_update_time_;
    if (delta.is_positive() && running_sequences_.size() > 1) {
      for (SequenceId id : running_sequences_) {
        Sequence* sequence = GetSequence(id);
        if (sequence) {
          sequence->current_task_concurrent_time_ += delta;
        }
      }
    }
  }
  last_concurrency_update_time_ = now;
}

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
