1
0
Fork 0
forked from wry/wry

tracy: move profiler facade into workspace crate

This commit is contained in:
kossLAN 2026-05-29 09:17:36 -04:00
parent 657e7ce2f7
commit b7ecf700fa
No known key found for this signature in database
7 changed files with 49 additions and 9 deletions

15
tracy/src/lib.rs Normal file
View file

@ -0,0 +1,15 @@
#[cfg(feature = "tracy")]
#[macro_use]
mod tracy_impl;
#[cfg(feature = "tracy")]
use tracy_impl as imp;
#[cfg(not(feature = "tracy"))]
#[macro_use]
mod tracy_noop;
#[cfg(not(feature = "tracy"))]
use tracy_noop as imp;
pub use imp::{FrameName, ZoneName, enable_profiler};

221
tracy/src/tracy_impl.rs Normal file
View file

@ -0,0 +1,221 @@
use {
ahash::AHashMap,
parking_lot::Mutex,
std::{
ffi::{CStr, CString},
ptr,
sync::{
LazyLock,
atomic::{AtomicBool, Ordering::Relaxed},
},
},
tracy_client_sys::{
___tracy_c_zone_context, ___tracy_emit_frame_mark_end, ___tracy_emit_frame_mark_start,
___tracy_emit_zone_end, ___tracy_source_location_data, ___tracy_startup_profiler,
},
};
#[derive(Copy, Clone)]
pub struct ZoneName {
data: &'static ZoneNameData,
}
struct ZoneNameData {
_name: CString,
loc: ___tracy_source_location_data,
}
unsafe impl Sync for ZoneNameData {}
unsafe impl Send for ZoneNameData {}
static CACHE: LazyLock<Mutex<AHashMap<String, ZoneName>>> = LazyLock::new(Default::default);
impl ZoneName {
pub fn __get(name: &str) -> Self {
let mut cache = CACHE.lock();
if let Some(span) = cache.get(name) {
return *span;
}
let cname = CString::new(name).unwrap();
let span = ZoneName {
data: Box::leak(Box::new(ZoneNameData {
loc: ___tracy_source_location_data {
name: cname.as_ptr(),
function: ptr::null(),
file: ptr::null(),
line: 0,
color: 0,
},
_name: cname,
})),
};
cache.insert(name.to_string(), span);
span
}
#[inline(always)]
pub fn __enter(self) -> RunningZone {
if enabled() {
unsafe {
let zone = tracy_client_sys::___tracy_emit_zone_begin(&self.data.loc, 1);
RunningZone(Some(zone))
}
} else {
RunningZone(None)
}
}
}
#[macro_export]
macro_rules! create_zone_name {
($($tt:tt)*) => {
$crate::ZoneName::__get(&format!($($tt)*))
};
}
pub struct RunningZone(Option<___tracy_c_zone_context>);
impl Drop for RunningZone {
#[inline(always)]
fn drop(&mut self) {
if let Some(zone) = self.0 {
unsafe {
___tracy_emit_zone_end(zone);
}
}
}
}
#[macro_export]
macro_rules! dynamic_raii_zone {
($name:expr) => {{
let name: ZoneName = $name;
name.__enter()
}};
}
#[macro_export]
macro_rules! dynamic_zone {
($name:expr) => {
let _zone = dynamic_raii_zone!($name);
};
}
#[macro_export]
macro_rules! raii_zone {
($($tt:tt)*) => {
{
static CACHE: std::sync::LazyLock<$crate::ZoneName> = std::sync::LazyLock::new(|| {
create_zone_name!($($tt)*)
});
CACHE.__enter()
}
};
}
#[macro_export]
macro_rules! zone {
($($tt:tt)*) => {
let _zone = raii_zone!($($tt)*);
};
}
#[derive(Copy, Clone)]
pub struct FrameName {
name: &'static CString,
}
static FRAME_CACHE: LazyLock<Mutex<AHashMap<String, FrameName>>> = LazyLock::new(Default::default);
impl FrameName {
pub fn get(name: &str) -> Self {
let mut cache = FRAME_CACHE.lock();
if let Some(frame_name) = cache.get(name) {
return *frame_name;
}
let cname = CString::new(name).unwrap();
let span = Self {
name: Box::leak(Box::new(cname)),
};
cache.insert(name.to_string(), span);
span
}
#[inline(always)]
pub fn __start(self) -> RenderingFrame {
if enabled() {
unsafe {
___tracy_emit_frame_mark_start(self.name.as_ptr());
}
}
RenderingFrame { name: self.name }
}
}
#[macro_export]
macro_rules! raii_frame {
($name:expr) => {{
let name: FrameName = $name;
name.__start()
}};
}
#[macro_export]
macro_rules! frame {
($name:expr) => {
let _frame = raii_frame!($name);
};
}
pub struct RenderingFrame {
name: &'static CString,
}
impl Drop for RenderingFrame {
#[inline(always)]
fn drop(&mut self) {
if enabled() {
unsafe {
___tracy_emit_frame_mark_end(self.name.as_ptr());
}
}
}
}
#[unsafe(no_mangle)]
unsafe extern "C" fn ___tracy_demangle(
mangled: *const std::ffi::c_char,
) -> *const std::ffi::c_char {
use std::io::Write;
if mangled.is_null() {
return ptr::null();
}
let Ok(mangled) = unsafe { CStr::from_ptr(mangled) }.to_str() else {
return ptr::null();
};
let demangled = rustc_demangle::demangle(mangled);
static mut BUF: Vec<u8> = Vec::new();
#[expect(clippy::deref_addrof)]
unsafe {
let buf = &mut *&raw mut BUF;
buf.clear();
if write!(buf, "{demangled:#}\0").is_err() {
return ptr::null();
}
buf.as_ptr().cast()
}
}
static ENABLED: AtomicBool = AtomicBool::new(false);
#[inline(always)]
fn enabled() -> bool {
ENABLED.load(Relaxed)
}
pub fn enable_profiler() {
unsafe {
___tracy_startup_profiler();
}
ENABLED.store(true, Relaxed);
}

58
tracy/src/tracy_noop.rs Normal file
View file

@ -0,0 +1,58 @@
#![allow(unused_macros)]
#[derive(Copy, Clone)]
pub struct ZoneName;
#[derive(Copy, Clone)]
pub struct FrameName;
impl FrameName {
pub fn get(_name: &str) -> Self {
Self
}
}
#[macro_export]
macro_rules! create_zone_name {
($($tt:tt)*) => {
$crate::ZoneName
};
}
#[macro_export]
macro_rules! dynamic_raii_zone {
($name:expr) => {};
}
#[macro_export]
macro_rules! dynamic_zone {
($name:expr) => {};
}
#[macro_export]
macro_rules! raii_zone {
($($tt:tt)*) => {
()
};
}
#[macro_export]
macro_rules! zone {
($($tt:tt)*) => {};
}
#[macro_export]
macro_rules! raii_frame {
($name:expr) => {
()
};
}
#[macro_export]
macro_rules! frame {
($name:expr) => {};
}
pub fn enable_profiler() {
// nothing
}