use std::sync::Arc;
use cudarc::driver::{CudaGraph, CudaStream};
pub fn capture_into_graph<F>(stream: &Arc<CudaStream>, body: F) -> Result<CudaGraph, String>
where
F: FnOnce() -> Result<(), String>,
{
stream
.synchronize()
.map_err(|e| format!("pre-capture sync: {e:?}"))?;
stream
.begin_capture(
cudarc::driver::sys::CUstreamCaptureMode::CU_STREAM_CAPTURE_MODE_THREAD_LOCAL,
)
.map_err(|e| format!("begin_capture: {e:?}"))?;
let body_result = body();
let end_result = stream.end_capture(
cudarc::driver::sys::CUgraphInstantiate_flags::CUDA_GRAPH_INSTANTIATE_FLAG_AUTO_FREE_ON_LAUNCH,
);
match (body_result, end_result) {
(Ok(()), Ok(Some(g))) => Ok(g),
(Ok(()), Ok(None)) => Err("end_capture returned no graph (empty body?)".to_string()),
(Ok(()), Err(e)) => Err(format!("end_capture: {e:?}")),
(Err(b), Ok(_)) => Err(format!("body: {b}")),
(Err(b), Err(e)) => Err(format!(
"body: {b}; end_capture ALSO failed (stream may be in invalid state): {e:?}"
)),
}
}