Repository: microsoft/onnxruntime
File: onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc (C++)

Code before:
    }
    m_current_graph_annotation_id = graph_annotation_id;
  }

  return Status::OK();
}

Status WebGpuExecutionProvider::OnRunEnd(bool /* sync_stream */, const onnxruntime::RunOptions& run_options) {
  context_.Flush(BufferManager());

  if (IsGraphCaptureEnabled() && !IsGraphCaptured(m_current_graph_annotation_id)) {
    if (m_current_graph_annotation_id != -1 && IsGraphCaptureAllowed()) {
      context_.CaptureEnd();
      is_graph_captured_ = true;
      ORT_RETURN_IF_ERROR(ReplayGraph(m_current_graph_annotation_id));
    } else {
      IncrementRegularRunCountBeforeGraphCapture();
    }
  }

  std::vector<WebGpuProfiler*> profilers;
  if (session_profiler_ && session_profiler_->Enabled()) {
    profilers.push_back(session_profiler_);
  }

  if (run_options.enable_profiling && tls_run_profiler_) {
    if (tls_run_profiler_->Enabled()) {
      profilers.push_back(tls_run_profiler_);
    }
    tls_run_profiler_ = nullptr;
  }

  if (!profilers.empty()) {
    context_.CollectProfilingData(profilers);
  }

#if defined(ENABLE_PIX_FOR_WEBGPU_EP)
  if (pix_frame_generator_) {
    pix_frame_generator_->GeneratePIXFrame();
  }
#endif  // ENABLE_PIX_FOR_WEBGPU_EP

  if (context_.ValidationMode() >= ValidationMode::Basic) {
    return context_.PopErrorScope();
  } else {
    return Status::OK();
  }
}

bool WebGpuExecutionProvider::IsGraphCaptureEnabled() const {
  return enable_graph_capture_;

Review comment (refactor):
>tls_run_profiler_ [](http://example.com/codeflow?start=38&length=17)

Why do we need TLS if RunOptions profiler is thread local already? TLS and RunOptions are two different things.
Also who is going to clean up TLS if we no longer need profiling, it would be better to keep everything on the stack or at least Run() scoped. #Resolved

Code after:

Status WebGpuExecutionProvider::OnRunEnd(bool /* sync_stream */, const onnxruntime::RunOptions& run_options) {
  context_.Flush(BufferManager());

  if (IsGraphCaptureEnabled() && !IsGraphCaptured(m_current_graph_annotation_id)) {
    if (m_current_graph_annotation_id != -1 && IsGraphCaptureAllowed()) {
      context_.CaptureEnd();
      is_graph_captured_ = true;
      ORT_RETURN_IF_ERROR(ReplayGraph(m_current_graph_annotation_id));
    } else {
      IncrementRegularRunCountBeforeGraphCapture();
    }
  }

  if ((session_profiler_ && session_profiler_->Enabled()) || run_options.enable_profiling) {
    context_.CollectProfilingData();
  }

#if defined(ENABLE_PIX_FOR_WEBGPU_EP)
  if (pix_frame_generator_) {
    pix_frame_generator_->GeneratePIXFrame();
  }
#endif  // ENABLE_PIX_FOR_WEBGPU_EP

  if (context_.ValidationMode() >= ValidationMode::Basic) {
    return context_.PopErrorScope();
  } else {
    return Status::OK();
  }
}

bool WebGpuExecutionProvider::IsGraphCaptureEnabled() const {
  return enable_graph_capture_;
}

bool WebGpuExecutionProvider::IsGraphCaptured(int graph_annotation_id) const {
  return is_graph_captured_ && graph_annotation_id != -1;
}

Status WebGpuExecutionProvider::ReplayGraph(int graph_annotation_id) {
  ORT_ENFORCE(IsGraphCaptured(graph_annotation_id));
  context_.Replay(captured_commands_, *graph_buffer_mgr_);
  return Status::OK();
}

webgpu::BufferManager& WebGpuExecutionProvider::BufferManager() const {
  if (graph_buffer_mgr_) {
    return *graph_buffer_mgr_;
  } else {
    return context_.BufferManager();
  }