#if defined(NVTX_AS_SYSTEM_HEADER)
#if defined(__clang__)
#pragma clang system_header
#elif defined(__GNUC__) || defined(__NVCOMPILER)
#pragma GCC system_header
#elif defined(_MSC_VER)
#pragma system_header
#endif
#endif
#define NVTX3_CPP_VERSION_MAJOR 1
#define NVTX3_CPP_VERSION_MINOR 2
#if !defined(NVTX3_CPP_REQUIRE_EXPLICIT_VERSION)
#define NVTX3_INLINE_THIS_VERSION
#if !defined(NVTX3_CPP_INLINED_VERSION_MAJOR)
#define NVTX3_CPP_INLINED_VERSION_MAJOR 1
#define NVTX3_CPP_INLINED_VERSION_MINOR 2
#elif NVTX3_CPP_INLINED_VERSION_MAJOR != NVTX3_CPP_VERSION_MAJOR
#error \
"Two different major versions of the NVTX C++ Wrappers are being included in a single .cpp file, with unversioned symbols enabled in both. Only one major version can enable unversioned symbols in a .cpp file. To disable unversioned symbols, #define NVTX3_CPP_REQUIRE_EXPLICIT_VERSION before #including nvtx3.hpp, and use the versioned symbols instead."
#elif (NVTX3_CPP_INLINED_VERSION_MAJOR == NVTX3_CPP_VERSION_MAJOR) && \
(NVTX3_CPP_INLINED_VERSION_MINOR < NVTX3_CPP_VERSION_MINOR)
#undef NVTX3_CPP_INLINED_VERSION_MINOR
#define NVTX3_CPP_INLINED_VERSION_MINOR 2
#endif
#endif
#if !defined(NVTX3_USE_CHECKED_OVERLOADS_FOR_GET)
#if defined(_MSC_VER) && _MSC_VER < 1914 \
|| defined(__GNUC__) && __GNUC__ == 8 && __GNUC_MINOR__ < 4
#define NVTX3_USE_CHECKED_OVERLOADS_FOR_GET 0
#else
#define NVTX3_USE_CHECKED_OVERLOADS_FOR_GET 1
#endif
#define NVTX3_USE_CHECKED_OVERLOADS_FOR_GET_DEFINED_HERE
#endif
#define NVTX3_CONCAT(A, B) A##B
#define NVTX3_NAMESPACE_FOR(VERSION) NVTX3_CONCAT(v, VERSION)
#define NVTX3_VERSION_NAMESPACE NVTX3_NAMESPACE_FOR(NVTX3_CPP_VERSION_MAJOR)
#define NVTX3_MINOR_NAMESPACE_FOR(VERSION) NVTX3_CONCAT(mv, VERSION)
#define NVTX3_MINOR_VERSION_NAMESPACE NVTX3_MINOR_NAMESPACE_FOR(NVTX3_CPP_VERSION_MINOR)
#if defined(NVTX3_INLINE_THIS_VERSION)
#define NVTX3_INLINE_IF_REQUESTED inline
#else
#define NVTX3_INLINE_IF_REQUESTED
#endif
#if __cpp_constexpr >= 201304L
#define NVTX3_CONSTEXPR_IF_CPP14 constexpr
#else
#define NVTX3_CONSTEXPR_IF_CPP14
#endif
#if __cplusplus >= 202002L
#define NVTX3_CONSTEXPR_IF_CPP20 constexpr
#else
#define NVTX3_CONSTEXPR_IF_CPP20
#endif
#if !defined(__has_cpp_attribute)
#define __has_cpp_attribute(x) 0
#endif
#if __has_cpp_attribute(maybe_unused)
#define NVTX3_MAYBE_UNUSED [[maybe_unused]]
#else
#define NVTX3_MAYBE_UNUSED
#endif
#if __has_cpp_attribute(nodiscard)
#define NVTX3_NO_DISCARD [[nodiscard]]
#else
#define NVTX3_NO_DISCARD
#endif
#if !defined(NVTX3_STATIC_ASSERT)
#define NVTX3_STATIC_ASSERT(condition, message) static_assert(condition, message)
#define NVTX3_STATIC_ASSERT_DEFINED_HERE
#endif
#ifndef NVTX3_CPP_DEFINITIONS_V1_0
#define NVTX3_CPP_DEFINITIONS_V1_0
#include "nvToolsExt.h"
#include "nvToolsExtCounters.h"
#include "nvToolsExtPayload.h"
#include "nvToolsExtPayloadHelper.h"
#include "nvToolsExtSemanticsCorrelation.h"
#include "nvToolsExtSemanticsCounters.h"
#include "nvToolsExtSemanticsScope.h"
#include "nvToolsExtSemanticsTime.h"
#include <memory>
#include <stdexcept>
#include <string>
#include <type_traits>
#include <utility>
#include <cstddef>
#include <cstdint>
namespace nvtx3 {
NVTX3_INLINE_IF_REQUESTED namespace NVTX3_VERSION_NAMESPACE
{
inline namespace NVTX3_MINOR_VERSION_NAMESPACE
{
namespace detail {
template <typename Unused>
struct always_false : std::false_type {};
template <typename T, typename = void>
struct has_name : std::false_type {};
template <typename T>
struct has_name<T, decltype((void)T::name, void())> : std::true_type {};
template <typename T, typename = void>
struct has_id : std::false_type {};
template <typename T>
struct has_id<T, decltype((void)T::id, void())> : std::true_type {};
template <typename T, typename = void>
struct has_message : std::false_type {};
template <typename T>
struct has_message<T, decltype((void)T::message, void())> : std::true_type {};
template <typename T, typename = void>
struct is_c_string : std::false_type {};
template <typename T>
struct is_c_string<T, typename std::enable_if<
std::is_convertible<T, char const* >::value ||
std::is_convertible<T, wchar_t const*>::value
>::type> : std::true_type {};
template <typename T>
using is_uint32 = std::is_same<typename std::decay<T>::type, uint32_t>;
template <typename... Args>
static inline void silence_unused(Args const&...) noexcept {}
template <typename T, typename TD>
struct has_data_member
{
private:
template <typename U>
static auto test_data(int) -> decltype(std::declval<const U>().data());
template <typename>
static auto test_data(...) -> void;
using return_type = decltype(test_data<T>(0));
public:
static constexpr bool value =
std::is_same<return_type, TD*>::value || std::is_same<return_type, TD const*>::value;
};
template <typename T>
struct has_size_member
{
private:
template <typename U>
static auto test_size(int) -> decltype(std::declval<const U>().size());
template <typename>
static auto test_size(...) -> void;
using return_type = decltype(test_size<T>(0));
public:
static constexpr bool value = !std::is_same<return_type, void>::value &&
std::is_convertible<return_type, size_t>::value;
};
template <typename W, typename U, typename = void>
struct is_safe_wrapper_of : std::false_type
{
};
template <typename W, typename U>
struct is_safe_wrapper_of<
W,
U,
typename std::enable_if<
std::is_standard_layout<W>::value && std::is_standard_layout<U>::value &&
std::is_trivially_copyable<W>::value && std::is_trivially_copyable<U>::value &&
sizeof(W) == sizeof(U)>::type> : std::true_type
{
};
template <typename DataType>
class semantic_base {
public:
nvtxSemanticsHeader_t const* get() const & noexcept
{
return reinterpret_cast<nvtxSemanticsHeader_t const*>(&data_);
}
protected:
explicit semantic_base(DataType const& data) noexcept : data_{data} {}
void set_next(nvtxSemanticsHeader_t const* next) noexcept
{
next_owner_.reset();
data_.header.next = next;
}
template <typename OtherDataType>
void own_next(semantic_base<OtherDataType> const& next)
{
auto owned_next = std::make_shared<semantic_base<OtherDataType>>(next);
data_.header.next = owned_next->get();
next_owner_ = owned_next;
}
DataType data_;
private:
std::shared_ptr<void const> next_owner_;
};
template <typename T>
struct counter_limit_traits;
template <>
struct counter_limit_traits<int64_t>
{
static constexpr int64_t limit_type_value = NVTX_COUNTER_LIMIT_I64;
static NVTX3_CONSTEXPR_IF_CPP20 void store(nvtxCounterLimit_t& slot, int64_t v) noexcept
{
slot.i64 = v;
}
};
template <>
struct counter_limit_traits<uint64_t>
{
static constexpr int64_t limit_type_value = NVTX_COUNTER_LIMIT_U64;
static NVTX3_CONSTEXPR_IF_CPP20 void store(nvtxCounterLimit_t& slot, uint64_t v) noexcept
{
slot.u64 = v;
}
};
template <>
struct counter_limit_traits<double>
{
static constexpr int64_t limit_type_value = NVTX_COUNTER_LIMIT_F64;
static NVTX3_CONSTEXPR_IF_CPP20 void store(nvtxCounterLimit_t& slot, double v) noexcept
{
slot.f64 = v;
}
};
}
class domain {
public:
domain(domain const&) = delete;
domain& operator=(domain const&) = delete;
domain(domain&&) = delete;
domain& operator=(domain&&) = delete;
struct global {
};
#if NVTX3_USE_CHECKED_OVERLOADS_FOR_GET
template <typename D = global,
typename std::enable_if<
detail::is_c_string<decltype(D::name)>::value
, int>::type = 0>
NVTX3_NO_DISCARD static domain const& get() noexcept
{
static domain const d(D::name);
return d;
}
template <typename D = global,
typename std::enable_if<
!detail::is_c_string<decltype(D::name)>::value
, int>::type = 0>
NVTX3_NO_DISCARD static domain const& get() noexcept
{
NVTX3_STATIC_ASSERT(detail::always_false<D>::value,
"Type used to identify an NVTX domain must contain a static constexpr member "
"called 'name' of type const char* or const wchar_t* -- 'name' member is not "
"convertible to either of those types");
static domain const unused;
return unused; }
template <typename D = global,
typename std::enable_if<
!detail::has_name<D>::value
, int>::type = 0>
NVTX3_NO_DISCARD static domain const& get() noexcept
{
NVTX3_STATIC_ASSERT(detail::always_false<D>::value,
"Type used to identify an NVTX domain must contain a static constexpr member "
"called 'name' of type const char* or const wchar_t* -- 'name' member is missing");
static domain const unused;
return unused; }
#else
template <typename D = global>
NVTX3_NO_DISCARD static domain const& get() noexcept
{
static domain const d(D::name);
return d;
}
#endif
operator nvtxDomainHandle_t() const noexcept { return _domain; }
private:
explicit domain(char const* name) noexcept : _domain{nvtxDomainCreateA(name)} {}
explicit domain(wchar_t const* name) noexcept : _domain{nvtxDomainCreateW(name)} {}
explicit domain(std::string const& name) noexcept : domain{name.c_str()} {}
explicit domain(std::wstring const& name) noexcept : domain{name.c_str()} {}
constexpr domain() noexcept {}
~domain() = default;
private:
nvtxDomainHandle_t const _domain{}; };
template <>
NVTX3_NO_DISCARD inline domain const& domain::get<domain::global>() noexcept
{
static domain const d{};
return d;
}
struct rgb {
using component_type = uint8_t;
constexpr rgb(
component_type red_,
component_type green_,
component_type blue_) noexcept
: red{red_}, green{green_}, blue{blue_}
{
}
component_type red{}; component_type green{}; component_type blue{}; };
struct argb final : rgb {
constexpr argb(
component_type alpha_,
component_type red_,
component_type green_,
component_type blue_) noexcept
: rgb{red_, green_, blue_}, alpha{alpha_}
{
}
component_type alpha{}; };
class color {
public:
using value_type = uint32_t;
constexpr explicit color(value_type hex_code) noexcept : _value{hex_code} {}
constexpr color(argb argb_) noexcept
: color{from_bytes_msb_to_lsb(argb_.alpha, argb_.red, argb_.green, argb_.blue)}
{
}
constexpr color(rgb rgb_) noexcept
: color{from_bytes_msb_to_lsb(0xFF, rgb_.red, rgb_.green, rgb_.blue)}
{
}
constexpr value_type get_value() const noexcept { return _value; }
constexpr nvtxColorType_t get_type() const noexcept { return _type; }
color() = delete;
~color() = default;
color(color const&) = default;
color& operator=(color const&) = default;
color(color&&) = default;
color& operator=(color&&) = default;
private:
constexpr static value_type from_bytes_msb_to_lsb(
uint8_t byte3,
uint8_t byte2,
uint8_t byte1,
uint8_t byte0) noexcept
{
return uint32_t{byte3} << 24 | uint32_t{byte2} << 16 | uint32_t{byte1} << 8 | uint32_t{byte0};
}
value_type _value{}; nvtxColorType_t _type{NVTX_COLOR_ARGB}; };
class category {
public:
using id_type = uint32_t;
constexpr explicit category(id_type id) noexcept : id_{id} {}
constexpr id_type get_id() const noexcept { return id_; }
category() = delete;
~category() = default;
category(category const&) = default;
category& operator=(category const&) = default;
category(category&&) = default;
category& operator=(category&&) = default;
private:
id_type id_{}; };
template <typename D = domain::global>
class named_category_in final : public category {
public:
#if NVTX3_USE_CHECKED_OVERLOADS_FOR_GET
template <typename C,
typename std::enable_if<
detail::is_c_string<decltype(C::name)>::value &&
detail::is_uint32<decltype(C::id)>::value
, int>::type = 0>
static named_category_in const& get() noexcept
{
static named_category_in const cat(C::id, C::name);
return cat;
}
template <typename C,
typename std::enable_if<
!detail::is_c_string<decltype(C::name)>::value ||
!detail::is_uint32<decltype(C::id)>::value
, int>::type = 0>
NVTX3_NO_DISCARD static named_category_in const& get() noexcept
{
NVTX3_STATIC_ASSERT(detail::is_c_string<decltype(C::name)>::value,
"Type used to name an NVTX category must contain a static constexpr member "
"called 'name' of type const char* or const wchar_t* -- 'name' member is not "
"convertible to either of those types");
NVTX3_STATIC_ASSERT(detail::is_uint32<decltype(C::id)>::value,
"Type used to name an NVTX category must contain a static constexpr member "
"called 'id' of type uint32_t -- 'id' member is the wrong type");
static named_category_in const unused;
return unused; }
template <typename C,
typename std::enable_if<
!detail::has_name<C>::value ||
!detail::has_id<C>::value
, int>::type = 0>
NVTX3_NO_DISCARD static named_category_in const& get() noexcept
{
NVTX3_STATIC_ASSERT(detail::has_name<C>::value,
"Type used to name an NVTX category must contain a static constexpr member "
"called 'name' of type const char* or const wchar_t* -- 'name' member is missing");
NVTX3_STATIC_ASSERT(detail::has_id<C>::value,
"Type used to name an NVTX category must contain a static constexpr member "
"called 'id' of type uint32_t -- 'id' member is missing");
static named_category_in const unused;
return unused; }
#else
template <typename C>
NVTX3_NO_DISCARD static named_category_in const& get() noexcept
{
static named_category_in const cat(C::id, C::name);
return cat;
}
#endif
private:
named_category_in() noexcept : category{0} {}
public:
named_category_in(id_type id, char const* name) noexcept : category{id}
{
#ifndef NVTX_DISABLE
nvtxDomainNameCategoryA(domain::get<D>(), get_id(), name);
#else
(void)id;
(void)name;
#endif
}
named_category_in(id_type id, std::string const& name) noexcept
: named_category_in{id, name.c_str()} {}
named_category_in(id_type id, wchar_t const* name) noexcept : category{id}
{
#ifndef NVTX_DISABLE
nvtxDomainNameCategoryW(domain::get<D>(), get_id(), name);
#else
(void)id;
(void)name;
#endif
}
named_category_in(id_type id, std::wstring const& name) noexcept
: named_category_in{id, name.c_str()} {}
};
using named_category = named_category_in<domain::global>;
template <typename D = domain::global>
class registered_string_in {
public:
#if NVTX3_USE_CHECKED_OVERLOADS_FOR_GET
template <typename M,
typename std::enable_if<
detail::is_c_string<decltype(M::message)>::value
, int>::type = 0>
NVTX3_NO_DISCARD static registered_string_in const& get() noexcept
{
static registered_string_in const regstr(M::message);
return regstr;
}
template <typename M,
typename std::enable_if<
!detail::is_c_string<decltype(M::message)>::value
, int>::type = 0>
NVTX3_NO_DISCARD static registered_string_in const& get() noexcept
{
NVTX3_STATIC_ASSERT(detail::always_false<M>::value,
"Type used to register an NVTX string must contain a static constexpr member "
"called 'message' of type const char* or const wchar_t* -- 'message' member is "
"not convertible to either of those types");
static registered_string_in const unused;
return unused; }
template <typename M,
typename std::enable_if<
!detail::has_message<M>::value
, int>::type = 0>
NVTX3_NO_DISCARD static registered_string_in const& get() noexcept
{
NVTX3_STATIC_ASSERT(detail::always_false<M>::value,
"Type used to register an NVTX string must contain a static constexpr member "
"called 'message' of type const char* or const wchar_t* -- 'message' member "
"is missing");
static registered_string_in const unused;
return unused; }
#else
template <typename M>
NVTX3_NO_DISCARD static registered_string_in const& get() noexcept
{
static registered_string_in const regstr(M::message);
return regstr;
}
#endif
explicit registered_string_in(char const* msg) noexcept
: handle_{nvtxDomainRegisterStringA(domain::get<D>(), msg)}
{
}
explicit registered_string_in(std::string const& msg) noexcept
: registered_string_in{msg.c_str()} {}
explicit registered_string_in(wchar_t const* msg) noexcept
: handle_{nvtxDomainRegisterStringW(domain::get<D>(), msg)}
{
}
explicit registered_string_in(std::wstring const& msg) noexcept
: registered_string_in{msg.c_str()} {}
nvtxStringHandle_t get_handle() const noexcept
{
NVTX3_STATIC_ASSERT(
(detail::is_safe_wrapper_of<registered_string_in<D>, nvtxStringHandle_t>::value),
"Internal error! registered_string_in is potentially unsafe.");
return handle_;
}
private:
registered_string_in() noexcept {}
public:
~registered_string_in() = default;
registered_string_in(registered_string_in const&) = default;
registered_string_in& operator=(registered_string_in const&) = default;
registered_string_in(registered_string_in&&) = default;
registered_string_in& operator=(registered_string_in&&) = default;
private:
nvtxStringHandle_t handle_{}; };
using registered_string = registered_string_in<domain::global>;
class message {
public:
using value_type = nvtxMessageValue_t;
NVTX3_CONSTEXPR_IF_CPP14 message(char const* msg) noexcept : type_{NVTX_MESSAGE_TYPE_ASCII}
{
value_.ascii = msg;
}
message(std::string const& msg) noexcept : message{msg.c_str()} {}
#ifndef NVTX3_ALLOW_RVALUE_CONSTRUCTORS
message(std::string&&) = delete;
#endif
NVTX3_CONSTEXPR_IF_CPP14 message(wchar_t const* msg) noexcept : type_{NVTX_MESSAGE_TYPE_UNICODE}
{
value_.unicode = msg;
}
message(std::wstring const& msg) noexcept : message{msg.c_str()} {}
#ifndef NVTX3_ALLOW_RVALUE_CONSTRUCTORS
message(std::wstring&&) = delete;
#endif
template <typename D>
NVTX3_CONSTEXPR_IF_CPP14 message(registered_string_in<D> const& msg) noexcept
: type_{NVTX_MESSAGE_TYPE_REGISTERED}
{
value_.registered = msg.get_handle();
}
constexpr message(
nvtxMessageType_t const& type,
nvtxMessageValue_t const& value) noexcept
: type_{type}, value_(value)
{
}
NVTX3_CONSTEXPR_IF_CPP14 message(nvtxStringHandle_t handle) noexcept
: type_{NVTX_MESSAGE_TYPE_REGISTERED}
{
value_.registered = handle;
}
constexpr value_type get_value() const noexcept { return value_; }
constexpr nvtxMessageType_t get_type() const noexcept { return type_; }
private:
nvtxMessageType_t type_{}; nvtxMessageValue_t value_{}; };
class payload {
public:
using value_type = typename nvtxEventAttributes_v2::payload_t;
NVTX3_CONSTEXPR_IF_CPP14 explicit payload(int64_t value) noexcept
: type_{NVTX_PAYLOAD_TYPE_INT64}, value_{}
{
value_.llValue = value;
}
NVTX3_CONSTEXPR_IF_CPP14 explicit payload(int32_t value) noexcept
: type_{NVTX_PAYLOAD_TYPE_INT32}, value_{}
{
value_.iValue = value;
}
NVTX3_CONSTEXPR_IF_CPP14 explicit payload(uint64_t value) noexcept
: type_{NVTX_PAYLOAD_TYPE_UNSIGNED_INT64}, value_{}
{
value_.ullValue = value;
}
NVTX3_CONSTEXPR_IF_CPP14 explicit payload(uint32_t value) noexcept
: type_{NVTX_PAYLOAD_TYPE_UNSIGNED_INT32}, value_{}
{
value_.uiValue = value;
}
NVTX3_CONSTEXPR_IF_CPP14 explicit payload(float value) noexcept
: type_{NVTX_PAYLOAD_TYPE_FLOAT}, value_{}
{
value_.fValue = value;
}
NVTX3_CONSTEXPR_IF_CPP14 explicit payload(double value) noexcept
: type_{NVTX_PAYLOAD_TYPE_DOUBLE}, value_{}
{
value_.dValue = value;
}
constexpr payload(
nvtxPayloadType_t const& type,
value_type const& value) noexcept
: type_{type}, value_(value)
{
}
constexpr value_type get_value() const noexcept { return value_; }
constexpr nvtxPayloadType_t get_type() const noexcept { return type_; }
private:
nvtxPayloadType_t type_; value_type value_; };
class schema
{
private:
schema()
: _schema_id{0}
{}
public:
schema(schema const&) = delete;
schema& operator=(schema const&) = delete;
schema(schema&&) = delete;
schema& operator=(schema&&) = delete;
explicit schema(uint64_t id)
: _schema_id{id}
{}
template <typename T>
NVTX3_NO_DISCARD static schema const& get() noexcept
{
NVTX3_STATIC_ASSERT(
detail::always_false<T>::value,
"payload_data schema deduction requires a template specialization. Use the macro "
"NVTX3_DEFINE_SCHEMA_GET to generate this specialization.");
static schema unused;
return unused;
}
uint64_t get_handle() const noexcept
{
return _schema_id;
}
private:
uint64_t const _schema_id;
};
class payload_data
{
public:
explicit payload_data(nvtxPayloadData_t const& pd)
: data_(pd)
{}
template <
typename R,
typename T = typename std::remove_cv<typename std::remove_reference<R>::type>::type,
typename = typename std::enable_if<!std::is_same<T, nvtxPayloadData_t>::value>::type>
explicit payload_data(R&& t)
: data_{schema::get<T>().get_handle(), sizeof(T), &t}
{
#ifndef NVTX3_ALLOW_RVALUE_CONSTRUCTORS
NVTX3_STATIC_ASSERT(
std::is_lvalue_reference<R>::value,
"payload_data requires an lvalue reference to the underlying data. Constructing "
"from an rvalue is potentially unsafe and therefore forbidden.");
#endif
NVTX3_STATIC_ASSERT(
std::is_standard_layout<T>::value && std::is_trivially_copyable<T>::value,
"structs used for NVTX3 payload schema must be standard layout and trivially copyable");
}
template <typename T>
explicit payload_data(T const& t, schema s)
: data_{s.get_handle(), sizeof(T), &t}
{
NVTX3_STATIC_ASSERT(
std::is_standard_layout<T>::value && std::is_trivially_copyable<T>::value,
"structs used for NVTX3 payload schema must be standard layout and trivially copyable");
}
uint64_t as_ull_value() const noexcept
{
NVTX3_STATIC_ASSERT(
(detail::is_safe_wrapper_of<payload_data, nvtxPayloadData_t>::value),
"Internal error! payload_data is potentially unsafe.");
return NVTX_POINTER_AS_PAYLOAD_ULLVALUE(&data_);
}
private:
nvtxPayloadData_t data_;
};
class event_attributes {
public:
using value_type = nvtxEventAttributes_t;
constexpr event_attributes() noexcept
: attributes_{
NVTX_VERSION, sizeof(nvtxEventAttributes_t), 0, NVTX_COLOR_UNKNOWN, 0, NVTX_PAYLOAD_UNKNOWN, 0, {0}, NVTX_MESSAGE_UNKNOWN, {nullptr} }
{
}
template <typename... Args>
NVTX3_CONSTEXPR_IF_CPP14 explicit event_attributes(category const& c, Args const&... args) noexcept
: event_attributes(args...)
{
attributes_.category = c.get_id();
}
template <typename... Args>
NVTX3_CONSTEXPR_IF_CPP14 explicit event_attributes(color const& c, Args const&... args) noexcept
: event_attributes(args...)
{
attributes_.color = c.get_value();
attributes_.colorType = c.get_type();
}
template <typename... Args>
NVTX3_CONSTEXPR_IF_CPP14 explicit event_attributes(payload const& p, Args const&... args) noexcept
: event_attributes(args...)
{
attributes_.payload = p.get_value();
attributes_.payloadType = p.get_type();
}
template <typename... Args>
NVTX3_CONSTEXPR_IF_CPP14 explicit event_attributes(payload_data const& pd, Args const&... args) noexcept
: event_attributes(args...)
{
attributes_.payloadType = NVTX_PAYLOAD_TYPE_EXT;
attributes_.reserved0 = 1;
attributes_.payload.ullValue = pd.as_ull_value();
}
#ifndef NVTX3_ALLOW_RVALUE_CONSTRUCTORS
template <typename... Args>
NVTX3_CONSTEXPR_IF_CPP14 explicit event_attributes(payload_data&& pd, Args const&... args) = delete;
#endif
template <
typename T,
typename... Args,
typename = typename std::enable_if<
detail::has_data_member<T, payload_data>::value && detail::has_size_member<T>::value>::type>
NVTX3_CONSTEXPR_IF_CPP20 explicit event_attributes(T&& pdc, Args const&... args) noexcept
: event_attributes(args...)
{
NVTX3_STATIC_ASSERT(
std::is_lvalue_reference<T>::value,
"event_attributes requires an lvalue reference to the underlying data. "
"Constructing from an rvalue is potentially unsafe and therefore forbidden.");
attributes_.payloadType = NVTX_PAYLOAD_TYPE_EXT;
attributes_.reserved0 = static_cast<int32_t>(pdc.size()); attributes_.payload.ullValue = pdc.data()->as_ull_value();
}
template <typename... Args>
NVTX3_CONSTEXPR_IF_CPP14 explicit event_attributes(message const& m, Args const&... args) noexcept
: event_attributes(args...)
{
attributes_.message = m.get_value();
attributes_.messageType = m.get_type();
}
~event_attributes() = default;
event_attributes(event_attributes const&) = default;
event_attributes& operator=(event_attributes const&) = default;
event_attributes(event_attributes&&) = default;
event_attributes& operator=(event_attributes&&) = default;
constexpr value_type const* get() const noexcept { return &attributes_; }
private:
value_type attributes_{}; };
template <class D = domain::global>
class NVTX3_MAYBE_UNUSED scoped_range_in {
public:
explicit scoped_range_in(event_attributes const& attr) noexcept
{
#ifndef NVTX_DISABLE
nvtxDomainRangePushEx(domain::get<D>(), attr.get());
#else
(void)attr;
#endif
}
template <typename... Args>
explicit scoped_range_in(Args const&... args) noexcept
: scoped_range_in{event_attributes{args...}}
{
}
scoped_range_in() noexcept : scoped_range_in{event_attributes{}} {}
void* operator new(std::size_t) = delete;
scoped_range_in(scoped_range_in const&) = delete;
scoped_range_in& operator=(scoped_range_in const&) = delete;
scoped_range_in(scoped_range_in&&) = delete;
scoped_range_in& operator=(scoped_range_in&&) = delete;
~scoped_range_in() noexcept
{
#ifndef NVTX_DISABLE
nvtxDomainRangePop(domain::get<D>());
#endif
}
};
using scoped_range = scoped_range_in<domain::global>;
template <typename D = domain::global>
inline int push_range_in(event_attributes const& attr) noexcept
{
#ifndef NVTX_DISABLE
return nvtxDomainRangePushEx(domain::get<D>(), attr.get());
#else
(void)attr;
return 0;
#endif
}
template <typename D = domain::global, typename... Args>
inline int push_range_in(Args const&... args) noexcept
{
#ifndef NVTX_DISABLE
return push_range_in<D>(event_attributes{args...});
#else
detail::silence_unused(args...);
return 0;
#endif
}
inline int push_range(event_attributes const& attr) noexcept
{
#ifndef NVTX_DISABLE
return push_range_in<domain::global>(attr);
#else
(void)attr;
return 0;
#endif
}
template <typename... Args>
inline int push_range(Args const&... args) noexcept
{
#ifndef NVTX_DISABLE
return push_range_in<domain::global>(args...);
#else
detail::silence_unused(args...);
return 0;
#endif
}
template <typename D = domain::global>
inline int pop_range_in() noexcept
{
#ifndef NVTX_DISABLE
return nvtxDomainRangePop(domain::get<D>());
#else
return 0;
#endif
}
inline int pop_range() noexcept
{
#ifndef NVTX_DISABLE
return pop_range_in<domain::global>();
#else
return 0;
#endif
}
namespace detail {
template <typename D = domain::global>
class NVTX3_MAYBE_UNUSED optional_scoped_range_in
{
public:
optional_scoped_range_in() = default;
void begin(event_attributes const& attr) noexcept
{
#ifndef NVTX_DISABLE
if (initialized) { return; }
nvtxDomainRangePushEx(domain::get<D>(), attr.get());
initialized = true;
#else
(void)attr;
#endif
}
~optional_scoped_range_in() noexcept
{
#ifndef NVTX_DISABLE
if (initialized) { nvtxDomainRangePop(domain::get<D>()); }
#endif
}
void* operator new(std::size_t) = delete;
optional_scoped_range_in(optional_scoped_range_in const&) = delete;
optional_scoped_range_in& operator=(optional_scoped_range_in const&) = delete;
optional_scoped_range_in(optional_scoped_range_in&&) = delete;
optional_scoped_range_in& operator=(optional_scoped_range_in&&) = delete;
private:
#ifndef NVTX_DISABLE
bool initialized = false;
#endif
};
}
struct range_handle {
using value_type = nvtxRangeId_t;
constexpr explicit range_handle(value_type id) noexcept : _range_id{id} {}
constexpr range_handle() noexcept = default;
constexpr explicit operator bool() const noexcept { return get_value() != null_range_id; }
constexpr range_handle(std::nullptr_t) noexcept {}
constexpr value_type get_value() const noexcept { return _range_id; }
private:
static constexpr value_type null_range_id = nvtxRangeId_t{0};
value_type _range_id{null_range_id}; };
inline constexpr bool operator==(range_handle lhs, range_handle rhs) noexcept
{
return lhs.get_value() == rhs.get_value();
}
inline constexpr bool operator!=(range_handle lhs, range_handle rhs) noexcept { return !(lhs == rhs); }
template <typename D = domain::global>
NVTX3_NO_DISCARD inline range_handle start_range_in(event_attributes const& attr) noexcept
{
#ifndef NVTX_DISABLE
return range_handle{nvtxDomainRangeStartEx(domain::get<D>(), attr.get())};
#else
(void)attr;
return {};
#endif
}
template <typename D = domain::global, typename... Args>
NVTX3_NO_DISCARD inline range_handle start_range_in(Args const&... args) noexcept
{
#ifndef NVTX_DISABLE
return start_range_in<D>(event_attributes{args...});
#else
detail::silence_unused(args...);
return {};
#endif
}
NVTX3_NO_DISCARD inline range_handle start_range(event_attributes const& attr) noexcept
{
#ifndef NVTX_DISABLE
return start_range_in<domain::global>(attr);
#else
(void)attr;
return {};
#endif
}
template <typename... Args>
NVTX3_NO_DISCARD inline range_handle start_range(Args const&... args) noexcept
{
#ifndef NVTX_DISABLE
return start_range_in<domain::global>(args...);
#else
detail::silence_unused(args...);
return {};
#endif
}
template <typename D = domain::global>
inline void end_range_in(range_handle r) noexcept
{
#ifndef NVTX_DISABLE
nvtxDomainRangeEnd(domain::get<D>(), r.get_value());
#else
(void)r;
#endif
}
inline void end_range(range_handle r) noexcept
{
#ifndef NVTX_DISABLE
end_range_in<domain::global>(r);
#else
(void)r;
#endif
}
template <typename D = domain::global>
class NVTX3_MAYBE_UNUSED unique_range_in {
public:
explicit unique_range_in(event_attributes const& attr) noexcept
: handle_{start_range_in<D>(attr)}
{
}
template <typename... Args>
explicit unique_range_in(Args const&... args) noexcept
: unique_range_in{event_attributes{args...}}
{
}
constexpr unique_range_in() noexcept : unique_range_in{event_attributes{}} {}
~unique_range_in() noexcept = default;
unique_range_in(unique_range_in&& other) noexcept = default;
unique_range_in& operator=(unique_range_in&& other) noexcept = default;
unique_range_in(unique_range_in const&) = delete;
unique_range_in& operator=(unique_range_in const&) = delete;
private:
struct end_range_handle {
using pointer = range_handle; void operator()(range_handle h) const noexcept { end_range_in<D>(h); }
};
std::unique_ptr<range_handle, end_range_handle> handle_;
};
using unique_range = unique_range_in<domain::global>;
template <typename D = domain::global>
inline void mark_in(event_attributes const& attr) noexcept
{
#ifndef NVTX_DISABLE
nvtxDomainMarkEx(domain::get<D>(), attr.get());
#else
(void)(attr);
#endif
}
template <typename D = domain::global, typename... Args>
inline void mark_in(Args const&... args) noexcept
{
#ifndef NVTX_DISABLE
mark_in<D>(event_attributes{args...});
#else
detail::silence_unused(args...);
#endif
}
inline void mark(event_attributes const& attr) noexcept
{
#ifndef NVTX_DISABLE
mark_in<domain::global>(attr);
#else
(void)attr;
#endif
}
template <typename... Args>
inline void mark(Args const&... args) noexcept
{
#ifndef NVTX_DISABLE
mark_in<domain::global>(args...);
#else
detail::silence_unused(args...);
#endif
}
class scope {
public:
using value_type = uint64_t;
constexpr explicit scope(value_type id) noexcept : id_{id} {}
constexpr value_type get() const noexcept { return id_; }
static constexpr scope none() noexcept { return scope{NVTX_SCOPE_NONE}; }
static constexpr scope root() noexcept { return scope{NVTX_SCOPE_ROOT}; }
static constexpr scope current_hw_machine() noexcept { return scope{NVTX_SCOPE_CURRENT_HW_MACHINE}; }
static constexpr scope current_hw_socket() noexcept { return scope{NVTX_SCOPE_CURRENT_HW_SOCKET}; }
static constexpr scope current_hw_cpu_physical() noexcept { return scope{NVTX_SCOPE_CURRENT_HW_CPU_PHYSICAL}; }
static constexpr scope current_hw_cpu_logical() noexcept { return scope{NVTX_SCOPE_CURRENT_HW_CPU_LOGICAL}; }
static constexpr scope current_hw_innermost() noexcept { return scope{NVTX_SCOPE_CURRENT_HW_INNERMOST}; }
static constexpr scope current_hypervisor() noexcept { return scope{NVTX_SCOPE_CURRENT_HYPERVISOR}; }
static constexpr scope current_vm() noexcept { return scope{NVTX_SCOPE_CURRENT_VM}; }
static constexpr scope current_kernel() noexcept { return scope{NVTX_SCOPE_CURRENT_KERNEL}; }
static constexpr scope current_container() noexcept { return scope{NVTX_SCOPE_CURRENT_CONTAINER}; }
static constexpr scope current_os() noexcept { return scope{NVTX_SCOPE_CURRENT_OS}; }
static constexpr scope current_sw_process() noexcept { return scope{NVTX_SCOPE_CURRENT_SW_PROCESS}; }
static constexpr scope current_sw_thread() noexcept { return scope{NVTX_SCOPE_CURRENT_SW_THREAD}; }
static constexpr scope current_sw_innermost() noexcept { return scope{NVTX_SCOPE_CURRENT_SW_INNERMOST}; }
private:
value_type id_;
};
namespace detail {
using scope_type = scope;
}
enum class no_value_reason : uint8_t {
zero = NVTX_COUNTER_SAMPLE_ZERO,
unchanged = NVTX_COUNTER_SAMPLE_UNCHANGED,
unavailable = NVTX_COUNTER_SAMPLE_UNAVAILABLE
};
class counter_semantic : public detail::semantic_base<nvtxSemanticsCounter_t> {
public:
counter_semantic() noexcept
: detail::semantic_base<nvtxSemanticsCounter_t>{
{{sizeof(nvtxSemanticsCounter_t), NVTX_SEMANTIC_ID_COUNTERS_V1,
NVTX_COUNTER_SEMANTIC_VERSION, nullptr},
NVTX_COUNTER_FLAGS_NONE,
nullptr,
1,
1,
NVTX_COUNTER_LIMIT_UNDEFINED,
{0},
{0}}}
{
}
explicit counter_semantic(nvtxSemanticsHeader_t const* next)
: counter_semantic{}
{
set_next(next);
}
template <typename OtherDataType>
explicit counter_semantic(detail::semantic_base<OtherDataType> const& next)
: counter_semantic{}
{
own_next(next);
}
counter_semantic& unit(const char* unit_name) noexcept
{
data_.unit = unit_name;
return *this;
}
counter_semantic& unit(std::string const& unit_name) noexcept
{
return unit(unit_name.c_str());
}
counter_semantic& unit(std::string&& unit_name) = delete;
counter_semantic& unit_scale(uint64_t numerator, uint64_t denominator = 1) noexcept
{
data_.unitScaleNumerator = numerator;
data_.unitScaleDenominator = denominator;
return *this;
}
counter_semantic& normalize() noexcept
{
data_.flags |= NVTX_COUNTER_FLAG_NORMALIZE;
return *this;
}
counter_semantic& valuetype_absolute()
{
set_enum_group_flag(NVTX_COUNTER_FLAG_VALUETYPES,
NVTX_COUNTER_FLAG_VALUETYPE_ABSOLUTE, "valuetype");
return *this;
}
counter_semantic& valuetype_delta()
{
set_enum_group_flag(NVTX_COUNTER_FLAG_VALUETYPES,
NVTX_COUNTER_FLAG_VALUETYPE_DELTA, "valuetype");
return *this;
}
counter_semantic& valuetype_delta_since_start()
{
set_enum_group_flag(NVTX_COUNTER_FLAG_VALUETYPES,
NVTX_COUNTER_FLAG_VALUETYPE_DELTA_SINCE_START, "valuetype");
return *this;
}
counter_semantic& interpolation_point()
{
set_enum_group_flag(NVTX_COUNTER_FLAG_INTERPOLATIONS,
NVTX_COUNTER_FLAG_INTERPOLATION_POINT, "interpolation");
return *this;
}
counter_semantic& interpolation_since_last()
{
set_enum_group_flag(NVTX_COUNTER_FLAG_INTERPOLATIONS,
NVTX_COUNTER_FLAG_INTERPOLATION_SINCE_LAST, "interpolation");
return *this;
}
counter_semantic& interpolation_until_next()
{
set_enum_group_flag(NVTX_COUNTER_FLAG_INTERPOLATIONS,
NVTX_COUNTER_FLAG_INTERPOLATION_UNTIL_NEXT, "interpolation");
return *this;
}
counter_semantic& interpolation_linear()
{
set_enum_group_flag(NVTX_COUNTER_FLAG_INTERPOLATIONS,
NVTX_COUNTER_FLAG_INTERPOLATION_LINEAR, "interpolation");
return *this;
}
template <typename T>
counter_semantic& limits(T min_val, T max_val) noexcept
{
using traits = detail::counter_limit_traits<T>;
data_.limitType = traits::limit_type_value;
data_.flags |= NVTX_COUNTER_FLAG_LIMITS;
traits::store(data_.min, min_val);
traits::store(data_.max, max_val);
return *this;
}
template <typename T>
counter_semantic& limit_min(T min_val) noexcept
{
using traits = detail::counter_limit_traits<T>;
data_.limitType = traits::limit_type_value;
data_.flags |= NVTX_COUNTER_FLAG_LIMIT_MIN;
traits::store(data_.min, min_val);
return *this;
}
template <typename T>
counter_semantic& limit_max(T max_val) noexcept
{
using traits = detail::counter_limit_traits<T>;
data_.limitType = traits::limit_type_value;
data_.flags |= NVTX_COUNTER_FLAG_LIMIT_MAX;
traits::store(data_.max, max_val);
return *this;
}
private:
void set_enum_group_flag(uint64_t group_mask, uint64_t value, char const* group_name)
{
if ((data_.flags & group_mask) != 0) {
throw std::logic_error(std::string("counter_semantic: conflicting ") + group_name
+ " setter; the " + group_name + " can be set only once");
}
data_.flags |= value;
}
};
class scope_semantic : public detail::semantic_base<nvtxSemanticsScope_t> {
public:
scope_semantic() noexcept
: detail::semantic_base<nvtxSemanticsScope_t>{
{{sizeof(nvtxSemanticsScope_t), NVTX_SEMANTIC_ID_SCOPE_V1,
NVTX_SCOPE_SEMANTIC_VERSION, nullptr},
NVTX_SCOPE_NONE}}
{
}
explicit scope_semantic(nvtxSemanticsHeader_t const* next)
: scope_semantic{}
{
set_next(next);
}
template <typename OtherDataType>
explicit scope_semantic(detail::semantic_base<OtherDataType> const& next)
: scope_semantic{}
{
own_next(next);
}
scope_semantic& scope(uint64_t scope_id) noexcept
{
data_.scopeId = scope_id;
return *this;
}
scope_semantic& scope(detail::scope_type s) noexcept
{
data_.scopeId = s.get();
return *this;
}
};
template <typename D = domain::global>
class scope_in {
public:
explicit scope_in(char const* path,
detail::scope_type parent = detail::scope_type::none(),
uint64_t static_id = NVTX_SCOPE_NONE) noexcept
{
#ifndef NVTX_DISABLE
nvtxScopeAttr_t attr{};
attr.structSize = sizeof(nvtxScopeAttr_t);
attr.path = path;
attr.parentScope = parent.get();
attr.scopeId = static_id;
id_ = nvtxScopeRegister(domain::get<D>(), &attr);
#else
(void)path;
(void)parent;
(void)static_id;
id_ = NVTX_SCOPE_NONE;
#endif
}
explicit scope_in(std::string const& path,
detail::scope_type parent = detail::scope_type::none(),
uint64_t static_id = NVTX_SCOPE_NONE) noexcept
: scope_in{path.c_str(), parent, static_id} {}
uint64_t id() const noexcept { return id_; }
operator detail::scope_type() const noexcept { return detail::scope_type{id_}; }
private:
uint64_t id_;
};
class time_semantic : public detail::semantic_base<nvtxSemanticsTime_t> {
public:
time_semantic() noexcept
: detail::semantic_base<nvtxSemanticsTime_t>{
{{sizeof(nvtxSemanticsTime_t), NVTX_SEMANTIC_ID_TIME_V1,
NVTX_TIME_SEMANTIC_VERSION, nullptr},
0}}
{
}
explicit time_semantic(nvtxSemanticsHeader_t const* next)
: time_semantic{}
{
set_next(next);
}
template <typename OtherDataType>
explicit time_semantic(detail::semantic_base<OtherDataType> const& next)
: time_semantic{}
{
own_next(next);
}
time_semantic& time_domain(uint64_t domain_id) noexcept
{
data_.timeDomainId = domain_id;
return *this;
}
};
inline int64_t timestamp() noexcept
{
#ifndef NVTX_DISABLE
return nvtxTimestampGet();
#else
return 0;
#endif
}
template <typename D = domain::global>
class time_domain_in {
public:
explicit time_domain_in(uint64_t timestamp_type_id,
detail::scope_type s = detail::scope_type::none(),
uint64_t timer_flags = NVTX_TIMER_FLAG_NONE,
int64_t timer_resolution = 0,
uint64_t timer_start = NVTX_TIMER_START_UNKNOWN,
uint64_t static_id = 0) noexcept
{
#ifndef NVTX_DISABLE
nvtxTimeDomainAttr_t attr{};
attr.scopeId = s.get();
attr.timestampTypeId = timestamp_type_id;
attr.timeDomainId = static_id;
attr.timerFlags = timer_flags;
attr.timerResolution = timer_resolution;
attr.timerStart = timer_start;
id_ = nvtxTimeDomainRegister(domain::get<D>(), &attr);
#else
(void)timestamp_type_id;
(void)s;
(void)timer_flags;
(void)timer_resolution;
(void)timer_start;
(void)static_id;
id_ = 0;
#endif
}
uint64_t id() const noexcept { return id_; }
void set_timer_source(uint64_t flags, int64_t (*provider)()) noexcept
{
#ifndef NVTX_DISABLE
nvtxTimerSource(domain::get<D>(), id_, flags, provider);
#else
(void)flags;
(void)provider;
#endif
}
void set_timer_source(uint64_t flags,
int64_t (*provider)(void*),
void* data) noexcept
{
#ifndef NVTX_DISABLE
nvtxTimerSourceWithData(domain::get<D>(), id_, flags, provider, data);
#else
(void)flags;
(void)provider;
(void)data;
#endif
}
void sync_point(uint64_t other_id, int64_t ts_self, int64_t ts_other) noexcept
{
#ifndef NVTX_DISABLE
nvtxTimeSyncPoint(domain::get<D>(), id_, other_id, ts_self, ts_other);
#else
(void)other_id;
(void)ts_self;
(void)ts_other;
#endif
}
void sync_point_table(uint64_t other_id,
nvtxSyncPoint_t const* points,
size_t count) noexcept
{
#ifndef NVTX_DISABLE
nvtxTimeSyncPointTable(domain::get<D>(), id_, other_id, points, count);
#else
(void)other_id;
(void)points;
(void)count;
#endif
}
void conversion_factor(uint64_t other_id,
double slope,
int64_t ts_self,
int64_t ts_other) noexcept
{
#ifndef NVTX_DISABLE
nvtxTimestampConversionFactor(domain::get<D>(), id_, other_id, slope, ts_self, ts_other);
#else
(void)other_id;
(void)slope;
(void)ts_self;
(void)ts_other;
#endif
}
private:
uint64_t id_;
};
class correlation_semantic : public detail::semantic_base<nvtxSemanticsCorrelation_t> {
public:
correlation_semantic() noexcept
: detail::semantic_base<nvtxSemanticsCorrelation_t>{
{{sizeof(nvtxSemanticsCorrelation_t), NVTX_SEMANTIC_ID_CORRELATION_V1,
NVTX_CORRELATION_SEMANTIC_VERSION, nullptr},
{0},
nullptr,
NVTX_CORRELATION_ROLE_NONE}}
{
}
explicit correlation_semantic(nvtxSemanticsHeader_t const* next)
: correlation_semantic{}
{
set_next(next);
}
template <typename OtherDataType>
explicit correlation_semantic(detail::semantic_base<OtherDataType> const& next)
: correlation_semantic{}
{
own_next(next);
}
correlation_semantic& domain_uuid(const unsigned char uuid[16]) noexcept
{
for (int i = 0; i < 16; ++i) {
data_.correlationDomainUuid[i] = uuid[i];
}
return *this;
}
correlation_semantic& display_name(const char* name) noexcept
{
data_.displayName = name;
return *this;
}
correlation_semantic& display_name(std::string const& name) noexcept
{
return display_name(name.c_str());
}
correlation_semantic& display_name(std::string&& name) = delete;
correlation_semantic& role(uint64_t role_id) noexcept
{
data_.role = role_id;
return *this;
}
};
namespace detail {
template <typename T, typename = void>
struct counter_schema_id {
static uint64_t get() noexcept
{
return schema::get<T>().get_handle();
}
};
template <>
struct counter_schema_id<int64_t> {
static constexpr uint64_t get() noexcept { return NVTX_PAYLOAD_ENTRY_TYPE_INT64; }
};
template <>
struct counter_schema_id<uint64_t> {
static constexpr uint64_t get() noexcept { return NVTX_PAYLOAD_ENTRY_TYPE_UINT64; }
};
template <>
struct counter_schema_id<int32_t> {
static constexpr uint64_t get() noexcept { return NVTX_PAYLOAD_ENTRY_TYPE_INT32; }
};
template <>
struct counter_schema_id<uint32_t> {
static constexpr uint64_t get() noexcept { return NVTX_PAYLOAD_ENTRY_TYPE_UINT32; }
};
template <>
struct counter_schema_id<double> {
static constexpr uint64_t get() noexcept { return NVTX_PAYLOAD_ENTRY_TYPE_FLOAT64; }
};
template <>
struct counter_schema_id<float> {
static constexpr uint64_t get() noexcept { return NVTX_PAYLOAD_ENTRY_TYPE_FLOAT; }
};
}
template <typename T, typename D = domain::global>
class counter_in {
public:
using value_type = T;
counter_in(const char* name, const char* description = nullptr, scope s = scope::none() ) noexcept
: counter_in{name, description, s, nullptr}
{
}
counter_in(std::string const& name, scope s = scope::none()) noexcept
: counter_in{name.c_str(), nullptr, s, nullptr}
{
}
counter_in(std::string const& name,
std::string const& description,
scope s = scope::none()) noexcept
: counter_in{name.c_str(), description.c_str(), s, nullptr}
{
}
counter_in(const char* name, const char* description, scope s, const counter_semantic& semantic) noexcept
: counter_in{name, description, s, &semantic}
{
}
counter_in(std::string const& name,
std::string const& description,
scope s,
const counter_semantic& semantic) noexcept
: counter_in{name.c_str(), description.c_str(), s, &semantic}
{
}
void sample(T const& value) noexcept
{
#ifndef NVTX_DISABLE
sample_impl(value, std::is_same<T, int64_t>{}, std::is_same<T, double>{});
#else
(void)value;
#endif
}
void sample_no_value(no_value_reason reason) noexcept
{
#ifndef NVTX_DISABLE
nvtxCounterSampleNoValue(domain::get<D>(), id_, static_cast<uint8_t>(reason));
#else
(void)reason;
#endif
}
void submit_batch(T const* values,
size_t count,
uint64_t flags = NVTX_BATCH_FLAG_TIME_SORTED) noexcept
{
submit_batch(values, count, nullptr, 0, flags);
}
void submit_batch(T const* values,
size_t count,
int64_t const* timestamps,
size_t timestamp_count,
uint64_t flags = NVTX_BATCH_FLAG_TIME_SORTED) noexcept
{
#ifndef NVTX_DISABLE
nvtxCounterBatch_t batch{};
batch.counterId = id_;
batch.counters = values;
batch.countersSize = count * sizeof(T);
batch.flags = flags;
batch.timestamps = timestamps;
batch.timestampsSize = timestamp_count * sizeof(int64_t);
nvtxCounterBatchSubmit(domain::get<D>(), &batch);
#else
(void)values;
(void)count;
(void)timestamps;
(void)timestamp_count;
(void)flags;
#endif
}
template <
typename CounterContainer,
typename = typename std::enable_if<
detail::has_data_member<CounterContainer, T>::value
&& detail::has_size_member<CounterContainer>::value>::type>
void submit_batch(CounterContainer const& values,
uint64_t flags = NVTX_BATCH_FLAG_TIME_SORTED) noexcept
{
submit_batch(values.data(), values.size(), flags);
}
template <
typename CounterContainer,
typename TimestampContainer,
typename = typename std::enable_if<
detail::has_data_member<CounterContainer, T>::value
&& detail::has_size_member<CounterContainer>::value
&& detail::has_data_member<TimestampContainer, int64_t>::value
&& detail::has_size_member<TimestampContainer>::value>::type>
void submit_batch(CounterContainer const& values,
TimestampContainer const& timestamps,
uint64_t flags = NVTX_BATCH_FLAG_TIME_SORTED) noexcept
{
submit_batch(values.data(), values.size(), timestamps.data(), timestamps.size(), flags);
}
uint64_t id() const noexcept { return id_; }
private:
counter_in(const char* name, const char* description, scope s, counter_semantic const* semantic) noexcept
{
#ifndef NVTX_DISABLE
nvtxCounterAttr_t attr{};
attr.structSize = sizeof(nvtxCounterAttr_t);
attr.schemaId = detail::counter_schema_id<T>::get();
attr.name = name;
attr.description = description;
attr.scopeId = s.get();
attr.semantics = semantic ? semantic->get() : nullptr;
id_ = nvtxCounterRegister(domain::get<D>(), &attr);
#else
(void)name;
(void)description;
(void)s;
(void)semantic;
#endif
}
void sample_impl(int64_t value, std::true_type , std::false_type) noexcept
{
nvtxCounterSampleInt64(domain::get<D>(), id_, value);
}
void sample_impl(double value, std::false_type, std::true_type ) noexcept
{
nvtxCounterSampleFloat64(domain::get<D>(), id_, value);
}
void sample_impl(T const& value, std::false_type, std::false_type) noexcept
{
nvtxCounterSample(domain::get<D>(), id_, &value, sizeof(T));
}
uint64_t id_{0};
};
template <typename T>
using counter = counter_in<T, domain::global>;
} } }
#ifndef NVTX_DISABLE
#define NVTX3_V1_FUNC_RANGE_IN(D) \
static ::nvtx3::v1::registered_string_in<D> const nvtx3_func_name__{__func__}; \
static ::nvtx3::v1::event_attributes const nvtx3_func_attr__{nvtx3_func_name__}; \
::nvtx3::v1::scoped_range_in<D> const nvtx3_range__{nvtx3_func_attr__}
#define NVTX3_V1_FUNC_RANGE_IF_IN(D, C) \
::nvtx3::v1::detail::optional_scoped_range_in<D> optional_nvtx3_range__; \
if (C) { \
static ::nvtx3::v1::registered_string_in<D> const nvtx3_func_name__{__func__}; \
static ::nvtx3::v1::event_attributes const nvtx3_func_attr__{nvtx3_func_name__}; \
optional_nvtx3_range__.begin(nvtx3_func_attr__); \
} (void)0
#else
#define NVTX3_V1_FUNC_RANGE_IN(D) (void)0
#define NVTX3_V1_FUNC_RANGE_IF_IN(D, C) (void)(C)
#endif
#define NVTX3_V1_FUNC_RANGE() NVTX3_V1_FUNC_RANGE_IN(::nvtx3::v1::domain::global)
#define NVTX3_V1_FUNC_RANGE_IF(C) NVTX3_V1_FUNC_RANGE_IF_IN(::nvtx3::v1::domain::global, C)
#if __has_cpp_attribute(nodiscard)
#define NVTX3_V1_NO_DISCARD [[nodiscard]]
#else
#define NVTX3_V1_NO_DISCARD
#endif
#define NVTX3_V1_DEFINE_SCHEMA_GET(dom, struct_id, schema_name, entries) \
template <> \
NVTX3_V1_NO_DISCARD inline nvtx3::v1::schema const& nvtx3::v1::schema::get<struct_id>() noexcept \
{ \
static_assert( \
std::is_standard_layout<struct_id>::value, \
"structs used for NVTX3 payload schema must be standard layout"); \
static_assert( \
std::is_trivially_copyable<struct_id>::value, \
"structs used for NVTX3 payload schema must be trivially copyable"); \
using nvtx_struct_id = struct_id; \
_NVTX_DEFINE_SCHEMA_FOR_STRUCT(nvtx_struct_id, schema_name, static const, entries) \
static const schema s{ \
nvtxPayloadSchemaRegister(nvtx3::v1::domain::get<dom>(), &nvtx_struct_id##Attr)}; \
return s; \
}
#define NVTX3_V1_SEMANTIC(expr) \
([]() -> nvtxSemanticsHeader_t const* { \
static auto const s_ = (expr); \
return s_.get(); \
}())
#if defined(NVTX3_INLINE_THIS_VERSION)
#define NVTX3_FUNC_RANGE NVTX3_V1_FUNC_RANGE
#define NVTX3_FUNC_RANGE_IF NVTX3_V1_FUNC_RANGE_IF
#define NVTX3_FUNC_RANGE_IN NVTX3_V1_FUNC_RANGE_IN
#define NVTX3_FUNC_RANGE_IF_IN NVTX3_V1_FUNC_RANGE_IF_IN
#define NVTX3_DEFINE_SCHEMA_GET NVTX3_V1_DEFINE_SCHEMA_GET
#define NVTX3_SEMANTIC NVTX3_V1_SEMANTIC
#endif
#endif
#undef NVTX3_CPP_VERSION_MAJOR
#undef NVTX3_CPP_VERSION_MINOR
#undef NVTX3_CONCAT
#undef NVTX3_NAMESPACE_FOR
#undef NVTX3_VERSION_NAMESPACE
#undef NVTX3_MINOR_NAMESPACE_FOR
#undef NVTX3_MINOR_VERSION_NAMESPACE
#undef NVTX3_INLINE_IF_REQUESTED
#undef NVTX3_CONSTEXPR_IF_CPP14
#undef NVTX3_CONSTEXPR_IF_CPP20
#undef NVTX3_MAYBE_UNUSED
#undef NVTX3_NO_DISCARD
#if defined(NVTX3_INLINE_THIS_VERSION)
#undef NVTX3_INLINE_THIS_VERSION
#endif
#if defined(NVTX3_USE_CHECKED_OVERLOADS_FOR_GET_DEFINED_HERE)
#undef NVTX3_USE_CHECKED_OVERLOADS_FOR_GET_DEFINED_HERE
#undef NVTX3_USE_CHECKED_OVERLOADS_FOR_GET
#endif
#if defined(NVTX3_STATIC_ASSERT_DEFINED_HERE)
#undef NVTX3_STATIC_ASSERT_DEFINED_HERE
#undef NVTX3_STATIC_ASSERT
#endif