1#![cfg_attr(test, allow(clippy::unwrap_used))]
5#![no_std]
6#![deny(unsafe_op_in_unsafe_fn)]
7
8pub mod ffi {
10 #![allow(non_upper_case_globals)]
11 #![allow(non_camel_case_types)]
12 #![allow(non_snake_case)]
13 include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
14}
15
16#[allow(clippy::cast_possible_truncation)]
18pub const NVTX_VERSION: i16 = ffi::NVTX_VERSION as i16;
20
21pub type RangeId = ffi::nvtxRangeId_t;
23
24pub type EventAttributes = ffi::nvtxEventAttributes_t;
26
27pub const NVTX_EVENT_ATTRIBUTES_SIZE: usize = core::mem::size_of::<EventAttributes>();
28
29pub type ResourceAttributes = ffi::nvtxResourceAttributes_t;
31
32pub const NVTX_RESOURCE_ATTRIBUTES_SIZE: usize = core::mem::size_of::<ResourceAttributes>();
33
34pub type SyncUserAttributes = ffi::nvtxSyncUserAttributes_t;
36
37pub const NVTX_SYNC_USER_ATTRIBUTES_SIZE: usize = core::mem::size_of::<SyncUserAttributes>();
38
39pub type ResourceAttributesIdentifier = ffi::nvtxResourceAttributes_v0_identifier_t;
41pub type ColorType = ffi::nvtxColorType_t;
43pub type MessageType = ffi::nvtxMessageType_t;
45pub type MessageValue = ffi::nvtxMessageValue_t;
47pub type PayloadType = ffi::nvtxPayloadType_t;
49pub type PayloadValue = ffi::nvtxEventAttributes_v2_payload_t;
51
52macro_rules! impl_from_repr_u32_enum_for_i32 {
54 ($($ty:ty),+ $(,)?) => {
55 $(
56 impl ::core::convert::From<$ty> for i32 {
57 fn from(value: $ty) -> Self {
58 value as i32
60 }
61 }
62 )+
63 };
64}
65
66impl_from_repr_u32_enum_for_i32!(ColorType, MessageType, PayloadType);
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71
72 fn assert_fits_nvtx_i32_field<T>(name: &str, value: T)
73 where
74 T: Into<i32>,
75 {
76 assert!(
77 value.into() >= 0,
78 "{name} must fit in NVTX's signed 32-bit type fields"
79 );
80 }
81
82 #[test]
83 fn enum_type_values_fit_nvtx_i32_fields() {
84 assert_fits_nvtx_i32_field("NVTX_COLOR_UNKNOWN", ColorType::NVTX_COLOR_UNKNOWN);
87 assert_fits_nvtx_i32_field("NVTX_COLOR_ARGB", ColorType::NVTX_COLOR_ARGB);
88
89 assert_fits_nvtx_i32_field("NVTX_MESSAGE_UNKNOWN", MessageType::NVTX_MESSAGE_UNKNOWN);
90 assert_fits_nvtx_i32_field(
91 "NVTX_MESSAGE_TYPE_ASCII",
92 MessageType::NVTX_MESSAGE_TYPE_ASCII,
93 );
94 assert_fits_nvtx_i32_field(
95 "NVTX_MESSAGE_TYPE_UNICODE",
96 MessageType::NVTX_MESSAGE_TYPE_UNICODE,
97 );
98 assert_fits_nvtx_i32_field(
99 "NVTX_MESSAGE_TYPE_REGISTERED",
100 MessageType::NVTX_MESSAGE_TYPE_REGISTERED,
101 );
102
103 assert_fits_nvtx_i32_field("NVTX_PAYLOAD_UNKNOWN", PayloadType::NVTX_PAYLOAD_UNKNOWN);
104 assert_fits_nvtx_i32_field(
105 "NVTX_PAYLOAD_TYPE_UNSIGNED_INT64",
106 PayloadType::NVTX_PAYLOAD_TYPE_UNSIGNED_INT64,
107 );
108 assert_fits_nvtx_i32_field(
109 "NVTX_PAYLOAD_TYPE_INT64",
110 PayloadType::NVTX_PAYLOAD_TYPE_INT64,
111 );
112 assert_fits_nvtx_i32_field(
113 "NVTX_PAYLOAD_TYPE_DOUBLE",
114 PayloadType::NVTX_PAYLOAD_TYPE_DOUBLE,
115 );
116 assert_fits_nvtx_i32_field(
117 "NVTX_PAYLOAD_TYPE_UNSIGNED_INT32",
118 PayloadType::NVTX_PAYLOAD_TYPE_UNSIGNED_INT32,
119 );
120 assert_fits_nvtx_i32_field(
121 "NVTX_PAYLOAD_TYPE_INT32",
122 PayloadType::NVTX_PAYLOAD_TYPE_INT32,
123 );
124 assert_fits_nvtx_i32_field(
125 "NVTX_PAYLOAD_TYPE_FLOAT",
126 PayloadType::NVTX_PAYLOAD_TYPE_FLOAT,
127 );
128 }
129}
130
131#[derive(Debug, Clone, Copy)]
133pub struct DomainHandle {
134 handle: ffi::nvtxDomainHandle_t,
135}
136
137unsafe impl Send for DomainHandle {}
140unsafe impl Sync for DomainHandle {}
142
143#[derive(Clone, Copy, PartialEq, Eq)]
145pub struct ResourceHandle {
146 handle: ffi::nvtxResourceHandle_t,
147}
148
149unsafe impl Send for ResourceHandle {}
151unsafe impl Sync for ResourceHandle {}
153
154#[derive(Debug, Clone, Copy, PartialEq, Eq)]
156pub struct StringHandle {
157 handle: ffi::nvtxStringHandle_t,
158}
159
160impl From<StringHandle> for ffi::nvtxStringHandle_t {
161 fn from(value: StringHandle) -> Self {
162 value.handle
163 }
164}
165
166unsafe impl Send for StringHandle {}
168unsafe impl Sync for StringHandle {}
170
171#[derive(Debug, Clone, Copy, PartialEq, Eq)]
173pub struct SyncUserHandle {
174 handle: ffi::nvtxSyncUser_t,
175}
176
177unsafe impl Send for SyncUserHandle {}
179unsafe impl Sync for SyncUserHandle {}
181
182#[cfg(feature = "cuda_runtime")]
183pub type CudaEvent = ffi::cudaEvent_t;
185#[cfg(feature = "cuda_runtime")]
186pub type CudaStream = ffi::cudaStream_t;
188
189#[cfg(feature = "cuda")]
190pub type CuContext = ffi::CUcontext;
192#[cfg(feature = "cuda")]
193pub type CuDevice = ffi::CUdevice;
195#[cfg(feature = "cuda")]
196pub type CuEvent = ffi::CUevent;
198#[cfg(feature = "cuda")]
199pub type CuStream = ffi::CUstream;
201
202pub mod resource_type {
204 #![allow(clippy::wildcard_imports)]
205 #![allow(clippy::unnecessary_cast)]
206
207 use crate::ffi::nvtxResourceGenericType_t::*;
208 pub const UNKNOWN: u32 = NVTX_RESOURCE_TYPE_UNKNOWN as u32;
212 pub const GENERIC_HANDLE: u32 = NVTX_RESOURCE_TYPE_GENERIC_HANDLE as u32;
214 pub const GENERIC_POINTER: u32 = NVTX_RESOURCE_TYPE_GENERIC_POINTER as u32;
216 pub const GENERIC_THREAD_NATIVE: u32 = NVTX_RESOURCE_TYPE_GENERIC_THREAD_NATIVE as u32;
218 pub const GENERIC_THREAD_POSIX: u32 = NVTX_RESOURCE_TYPE_GENERIC_THREAD_POSIX as u32;
220
221 #[cfg(feature = "cuda")]
222 mod cuda {
223 use crate::ffi::nvtxResourceCUDAType_t::*;
224 pub const CUDA_DEVICE: u32 = NVTX_RESOURCE_TYPE_CUDA_DEVICE as u32;
227 pub const CUDA_CONTEXT: u32 = NVTX_RESOURCE_TYPE_CUDA_CONTEXT as u32;
229 pub const CUDA_STREAM: u32 = NVTX_RESOURCE_TYPE_CUDA_STREAM as u32;
231 pub const CUDA_EVENT: u32 = NVTX_RESOURCE_TYPE_CUDA_EVENT as u32;
233 }
234 #[cfg(feature = "cuda")]
235 pub use cuda::*;
236
237 #[cfg(feature = "cuda_runtime")]
238 mod cuda_runtime {
239 use crate::ffi::nvtxResourceCUDARTType_t::*;
240 pub const CUDART_DEVICE: u32 = NVTX_RESOURCE_TYPE_CUDART_DEVICE as u32;
243 pub const CUDART_STREAM: u32 = NVTX_RESOURCE_TYPE_CUDART_STREAM as u32;
245 pub const CUDART_EVENT: u32 = NVTX_RESOURCE_TYPE_CUDART_EVENT as u32;
247 }
248 #[cfg(feature = "cuda_runtime")]
249 pub use cuda_runtime::*;
250
251 #[cfg(target_family = "unix")]
252 mod pthread {
253 use crate::ffi::nvtxResourceSyncPosixThreadType_t::*;
254 pub const PTHREAD_MUTEX: u32 = NVTX_RESOURCE_TYPE_SYNC_PTHREAD_MUTEX as u32;
257 pub const PTHREAD_CONDITION: u32 = NVTX_RESOURCE_TYPE_SYNC_PTHREAD_CONDITION as u32;
259 pub const PTHREAD_RWLOCK: u32 = NVTX_RESOURCE_TYPE_SYNC_PTHREAD_RWLOCK as u32;
261 pub const PTHREAD_BARRIER: u32 = NVTX_RESOURCE_TYPE_SYNC_PTHREAD_BARRIER as u32;
263 pub const PTHREAD_SPINLOCK: u32 = NVTX_RESOURCE_TYPE_SYNC_PTHREAD_SPINLOCK as u32;
265 pub const PTHREAD_ONCE: u32 = NVTX_RESOURCE_TYPE_SYNC_PTHREAD_ONCE as u32;
267 }
268 #[cfg(target_family = "unix")]
269 pub use pthread::*;
270}
271
272use core::ffi::CStr;
273use widestring::WideCStr;
274
275pub fn domain_mark_ex(domain: DomainHandle, event_attrib: &EventAttributes) {
277 unsafe { crate::ffi::nvtxDomainMarkEx(domain.handle, event_attrib) }
279}
280
281pub fn mark_ex(event_attrib: &EventAttributes) {
283 unsafe { crate::ffi::nvtxMarkEx(event_attrib) }
285}
286
287pub fn mark_ascii(message: &CStr) {
289 unsafe { crate::ffi::nvtxMarkA(message.as_ptr()) }
291}
292
293pub fn mark_unicode(message: &WideCStr) {
295 unsafe { crate::ffi::nvtxMarkW(message.as_ptr().cast()) }
297}
298
299#[must_use]
300pub fn domain_range_start_ex(domain: DomainHandle, event_attrib: &EventAttributes) -> RangeId {
304 unsafe { crate::ffi::nvtxDomainRangeStartEx(domain.handle, event_attrib) }
306}
307
308#[must_use]
309pub fn range_start_ex(event_attrib: &EventAttributes) -> RangeId {
313 unsafe { crate::ffi::nvtxRangeStartEx(event_attrib) }
315}
316
317#[must_use]
318pub fn range_start_ascii(message: &CStr) -> RangeId {
322 unsafe { crate::ffi::nvtxRangeStartA(message.as_ptr()) }
324}
325
326#[must_use]
327pub fn range_start_unicode(message: &WideCStr) -> RangeId {
331 unsafe { crate::ffi::nvtxRangeStartW(message.as_ptr().cast()) }
333}
334
335pub fn domain_range_end(domain: DomainHandle, id: RangeId) {
339 unsafe { crate::ffi::nvtxDomainRangeEnd(domain.handle, id) }
341}
342
343pub fn range_end(id: RangeId) {
350 unsafe { crate::ffi::nvtxRangeEnd(id) }
352}
353
354#[allow(clippy::must_use_candidate)]
355pub fn domain_range_push_ex(domain: DomainHandle, event_attrib: &EventAttributes) -> i32 {
359 unsafe { crate::ffi::nvtxDomainRangePushEx(domain.handle, event_attrib) }
361}
362
363#[allow(clippy::must_use_candidate)]
364pub fn range_push_ex(event_attrib: &EventAttributes) -> i32 {
368 unsafe { crate::ffi::nvtxRangePushEx(event_attrib) }
370}
371
372#[allow(clippy::must_use_candidate)]
373pub fn range_push_ascii(message: &CStr) -> i32 {
377 unsafe { crate::ffi::nvtxRangePushA(message.as_ptr()) }
379}
380
381#[allow(clippy::must_use_candidate)]
382pub fn range_push_unicode(message: &WideCStr) -> i32 {
386 unsafe { crate::ffi::nvtxRangePushW(message.as_ptr().cast()) }
388}
389
390#[allow(clippy::must_use_candidate)]
391pub fn domain_range_pop(domain: DomainHandle) -> i32 {
395 unsafe { crate::ffi::nvtxDomainRangePop(domain.handle) }
397}
398
399#[allow(clippy::must_use_candidate)]
400pub fn range_pop() -> i32 {
407 unsafe { crate::ffi::nvtxRangePop() }
409}
410
411#[must_use]
412pub fn domain_resource_create(domain: DomainHandle, attribs: ResourceAttributes) -> ResourceHandle {
416 ResourceHandle {
417 handle: unsafe {
419 crate::ffi::nvtxDomainResourceCreate(
420 domain.handle,
421 core::ptr::addr_of!(attribs).cast_mut(),
422 )
423 },
424 }
425}
426
427pub fn domain_resource_destroy(resource: ResourceHandle) {
431 unsafe { crate::ffi::nvtxDomainResourceDestroy(resource.handle) }
433}
434
435pub fn domain_name_category_ascii(domain: DomainHandle, category: u32, name: &CStr) {
437 unsafe { crate::ffi::nvtxDomainNameCategoryA(domain.handle, category, name.as_ptr()) }
439}
440
441pub fn domain_name_category_unicode(domain: DomainHandle, category: u32, name: &WideCStr) {
443 unsafe { crate::ffi::nvtxDomainNameCategoryW(domain.handle, category, name.as_ptr().cast()) }
445}
446
447pub fn name_category_ascii(category: u32, name: &CStr) {
449 unsafe { crate::ffi::nvtxNameCategoryA(category, name.as_ptr()) }
451}
452
453pub fn name_category_unicode(category: u32, name: &WideCStr) {
455 unsafe { crate::ffi::nvtxNameCategoryW(category, name.as_ptr().cast()) }
457}
458
459pub fn name_os_thread_ascii(thread_id: u32, name: &CStr) {
463 unsafe { crate::ffi::nvtxNameOsThreadA(thread_id, name.as_ptr()) }
465}
466
467pub fn name_os_thread_unicode(thread_id: u32, name: &WideCStr) {
471 unsafe { crate::ffi::nvtxNameOsThreadW(thread_id, name.as_ptr().cast()) }
473}
474
475#[must_use]
476pub fn domain_register_string_ascii(domain: DomainHandle, string: &CStr) -> StringHandle {
478 StringHandle {
479 handle: unsafe { crate::ffi::nvtxDomainRegisterStringA(domain.handle, string.as_ptr()) },
481 }
482}
483
484#[must_use]
485pub fn domain_register_string_unicode(domain: DomainHandle, string: &WideCStr) -> StringHandle {
487 StringHandle {
488 handle: unsafe {
490 crate::ffi::nvtxDomainRegisterStringW(domain.handle, string.as_ptr().cast())
491 },
492 }
493}
494
495#[must_use]
496pub fn domain_create_ascii(name: &CStr) -> DomainHandle {
498 DomainHandle {
499 handle: unsafe { crate::ffi::nvtxDomainCreateA(name.as_ptr()) },
501 }
502}
503
504#[must_use]
505pub fn domain_create_unicode(name: &WideCStr) -> DomainHandle {
507 DomainHandle {
508 handle: unsafe { crate::ffi::nvtxDomainCreateW(name.as_ptr().cast()) },
510 }
511}
512
513pub fn domain_destroy(domain: DomainHandle) {
517 unsafe { crate::ffi::nvtxDomainDestroy(domain.handle) }
519}
520
521#[cfg(feature = "cuda")]
522pub fn name_cudevice_ascii(device: CuDevice, name: &CStr) {
524 unsafe { crate::ffi::nvtxNameCuDeviceA(device, name.as_ptr()) }
526}
527
528#[cfg(feature = "cuda")]
529pub fn name_cudevice_unicode(device: CuDevice, name: &WideCStr) {
531 unsafe { crate::ffi::nvtxNameCuDeviceW(device, name.as_ptr().cast()) }
533}
534
535#[cfg(feature = "cuda")]
536pub unsafe fn name_cucontext_ascii(context: CuContext, name: &CStr) {
541 unsafe { crate::ffi::nvtxNameCuContextA(context, name.as_ptr()) }
543}
544
545#[cfg(feature = "cuda")]
546pub unsafe fn name_cucontext_unicode(context: CuContext, name: &WideCStr) {
551 unsafe { crate::ffi::nvtxNameCuContextW(context, name.as_ptr().cast()) }
553}
554
555#[cfg(feature = "cuda")]
556pub unsafe fn name_custream_ascii(stream: CuStream, name: &CStr) {
561 unsafe { crate::ffi::nvtxNameCuStreamA(stream, name.as_ptr()) }
563}
564
565#[cfg(feature = "cuda")]
566pub unsafe fn name_custream_unicode(stream: CuStream, name: &WideCStr) {
571 unsafe { crate::ffi::nvtxNameCuStreamW(stream, name.as_ptr().cast()) }
573}
574
575#[cfg(feature = "cuda")]
576pub unsafe fn name_cuevent_ascii(event: CuEvent, name: &CStr) {
581 unsafe { crate::ffi::nvtxNameCuEventA(event, name.as_ptr()) }
583}
584
585#[cfg(feature = "cuda")]
586pub unsafe fn name_cuevent_unicode(event: CuEvent, name: &WideCStr) {
591 unsafe { crate::ffi::nvtxNameCuEventW(event, name.as_ptr().cast()) }
593}
594
595#[cfg(feature = "cuda_runtime")]
596pub fn name_cuda_device_ascii(device: i32, name: &CStr) {
598 unsafe { crate::ffi::nvtxNameCudaDeviceA(device, name.as_ptr()) }
600}
601
602#[cfg(feature = "cuda_runtime")]
603pub fn name_cuda_device_unicode(device: i32, name: &WideCStr) {
605 unsafe { crate::ffi::nvtxNameCudaDeviceW(device, name.as_ptr().cast()) }
607}
608
609#[cfg(feature = "cuda_runtime")]
610pub unsafe fn name_cuda_stream_ascii(stream: CudaStream, name: &CStr) {
615 unsafe { crate::ffi::nvtxNameCudaStreamA(stream, name.as_ptr()) }
617}
618
619#[cfg(feature = "cuda_runtime")]
620pub unsafe fn name_cuda_stream_unicode(stream: CudaStream, name: &WideCStr) {
625 unsafe { crate::ffi::nvtxNameCudaStreamW(stream, name.as_ptr().cast()) }
627}
628
629#[cfg(feature = "cuda_runtime")]
630pub unsafe fn name_cuda_event_ascii(event: CudaEvent, name: &CStr) {
635 unsafe { crate::ffi::nvtxNameCudaEventA(event, name.as_ptr()) }
637}
638
639#[cfg(feature = "cuda_runtime")]
640pub unsafe fn name_cuda_event_unicode(event: CudaEvent, name: &WideCStr) {
645 unsafe { crate::ffi::nvtxNameCudaEventW(event, name.as_ptr().cast()) }
647}
648
649#[must_use]
650pub fn domain_syncuser_create(domain: DomainHandle, attribs: SyncUserAttributes) -> SyncUserHandle {
652 SyncUserHandle {
653 handle: unsafe {
655 crate::ffi::nvtxDomainSyncUserCreate(
656 domain.handle,
657 core::ptr::addr_of!(attribs).cast_mut(),
658 )
659 },
660 }
661}
662
663pub fn domain_syncuser_destroy(handle: SyncUserHandle) {
667 unsafe { crate::ffi::nvtxDomainSyncUserDestroy(handle.handle) }
669}
670
671pub fn domain_syncuser_acquire_start(handle: SyncUserHandle) {
673 unsafe { crate::ffi::nvtxDomainSyncUserAcquireStart(handle.handle) }
675}
676
677pub fn domain_syncuser_acquire_failed(handle: SyncUserHandle) {
681 unsafe { crate::ffi::nvtxDomainSyncUserAcquireFailed(handle.handle) }
683}
684
685pub fn domain_syncuser_acquire_success(handle: SyncUserHandle) {
689 unsafe { crate::ffi::nvtxDomainSyncUserAcquireSuccess(handle.handle) }
691}
692
693pub fn domain_syncuser_acquire_releasing(handle: SyncUserHandle) {
697 unsafe { crate::ffi::nvtxDomainSyncUserReleasing(handle.handle) }
699}