352 lines
11 KiB
Zig
352 lines
11 KiB
Zig
const std = @import("std");
|
|
const digits2 = std.fmt.digits2;
|
|
const builtin = @import("builtin");
|
|
|
|
const options = @import("options");
|
|
|
|
const c = @import("c");
|
|
|
|
pub inline fn setThreadName(comptime name: [:0]const u8) void {
|
|
if (!options.tracy_enable) return;
|
|
c.___tracy_set_thread_name(name);
|
|
}
|
|
|
|
pub inline fn startupProfiler() void {
|
|
if (!options.tracy_enable) return;
|
|
if (!options.tracy_manual_lifetime) return;
|
|
c.___tracy_startup_profiler();
|
|
}
|
|
|
|
pub inline fn shutdownProfiler() void {
|
|
if (!options.tracy_enable) return;
|
|
if (!options.tracy_manual_lifetime) return;
|
|
c.___tracy_shutdown_profiler();
|
|
}
|
|
|
|
pub inline fn profilerStarted() bool {
|
|
if (!options.tracy_enable) return false;
|
|
if (!options.tracy_manual_lifetime) return true;
|
|
return c.___tracy_profiler_started() != 0;
|
|
}
|
|
|
|
pub inline fn isConnected() bool {
|
|
if (!options.tracy_enable) return false;
|
|
return c.___tracy_connected() > 0;
|
|
}
|
|
|
|
pub inline fn frameMark() void {
|
|
if (!options.tracy_enable) return;
|
|
c.___tracy_emit_frame_mark(null);
|
|
}
|
|
|
|
pub inline fn frameMarkNamed(comptime name: [:0]const u8) void {
|
|
if (!options.tracy_enable) return;
|
|
c.___tracy_emit_frame_mark(name);
|
|
}
|
|
|
|
const DiscontinuousFrame = struct {
|
|
name: [:0]const u8,
|
|
|
|
pub inline fn deinit(frame: *const DiscontinuousFrame) void {
|
|
if (!options.tracy_enable) return;
|
|
c.___tracy_emit_frame_mark_end(frame.name);
|
|
}
|
|
};
|
|
|
|
pub inline fn initDiscontinuousFrame(comptime name: [:0]const u8) DiscontinuousFrame {
|
|
if (!options.tracy_enable) return .{ .name = name };
|
|
c.___tracy_emit_frame_mark_start(name);
|
|
return .{ .name = name };
|
|
}
|
|
|
|
pub inline fn frameImage(image: *anyopaque, width: u16, height: u16, offset: u8, flip: bool) void {
|
|
if (!options.tracy_enable) return;
|
|
c.___tracy_emit_frame_mark_image(image, width, height, offset, @as(c_int, @intFromBool(flip)));
|
|
}
|
|
|
|
pub const ZoneOptions = struct {
|
|
active: bool = true,
|
|
name: ?[]const u8 = null,
|
|
color: ?u32 = null,
|
|
};
|
|
|
|
const ZoneContext = if (options.tracy_enable) extern struct {
|
|
ctx: c.___tracy_c_zone_context,
|
|
|
|
pub inline fn deinit(zone: *const ZoneContext) void {
|
|
if (!options.tracy_enable) return;
|
|
c.___tracy_emit_zone_end(zone.ctx);
|
|
}
|
|
|
|
pub inline fn name(zone: *const ZoneContext, zone_name: []const u8) void {
|
|
if (!options.tracy_enable) return;
|
|
c.___tracy_emit_zone_name(zone.ctx, zone_name.ptr, zone_name.len);
|
|
}
|
|
|
|
pub inline fn text(zone: *const ZoneContext, zone_text: []const u8) void {
|
|
if (!options.tracy_enable) return;
|
|
c.___tracy_emit_zone_text(zone.ctx, zone_text.ptr, zone_text.len);
|
|
}
|
|
|
|
pub inline fn color(zone: *const ZoneContext, zone_color: u32) void {
|
|
if (!options.tracy_enable) return;
|
|
c.___tracy_emit_zone_color(zone.ctx, zone_color);
|
|
}
|
|
|
|
pub inline fn value(zone: *const ZoneContext, zone_value: u64) void {
|
|
if (!options.tracy_enable) return;
|
|
c.___tracy_emit_zone_value(zone.ctx, zone_value);
|
|
}
|
|
} else struct {
|
|
pub inline fn deinit(_: *const ZoneContext) void {}
|
|
pub inline fn name(_: *const ZoneContext, _: []const u8) void {}
|
|
pub inline fn text(_: *const ZoneContext, _: []const u8) void {}
|
|
pub inline fn color(_: *const ZoneContext, _: u32) void {}
|
|
pub inline fn value(_: *const ZoneContext, _: u64) void {}
|
|
};
|
|
|
|
pub inline fn initZone(comptime src: std.builtin.SourceLocation, comptime opts: ZoneOptions) ZoneContext {
|
|
if (!options.tracy_enable) return .{};
|
|
const active: c_int = @intFromBool(opts.active);
|
|
|
|
const static = struct {
|
|
var src_loc = c.___tracy_source_location_data{
|
|
.name = if (opts.name) |name| name.ptr else null,
|
|
.function = src.fn_name.ptr,
|
|
.file = src.file,
|
|
.line = 0,
|
|
.color = opts.color orelse 0,
|
|
};
|
|
};
|
|
|
|
// src.line magically is not comptime https://github.com/ziglang/zig/pull/12016#issuecomment-1178092847
|
|
static.src_loc.line = src.line;
|
|
|
|
if (!options.tracy_no_callstack) {
|
|
if (options.tracy_callstack) |depth| {
|
|
return .{
|
|
.ctx = c.___tracy_emit_zone_begin_callstack(&static.src_loc, depth, active),
|
|
};
|
|
}
|
|
}
|
|
|
|
return .{
|
|
.ctx = c.___tracy_emit_zone_begin(&static.src_loc, active),
|
|
};
|
|
}
|
|
|
|
pub inline fn plot(comptime T: type, comptime name: [:0]const u8, value: T) void {
|
|
if (!options.tracy_enable) return;
|
|
|
|
const type_info = @typeInfo(T);
|
|
switch (type_info) {
|
|
.int => |int_type| {
|
|
if (int_type.bits > 64) @compileError("Too large int to plot");
|
|
if (int_type.signedness == .unsigned and int_type.bits > 63) @compileError("Too large unsigned int to plot");
|
|
c.___tracy_emit_plot_int(name, value);
|
|
},
|
|
.float => |float_type| {
|
|
if (float_type.bits <= 32) {
|
|
c.___tracy_emit_plot_float(name, value);
|
|
} else if (float_type.bits <= 64) {
|
|
c.___tracy_emit_plot(name, value);
|
|
} else {
|
|
@compileError("Too large float to plot");
|
|
}
|
|
},
|
|
else => @compileError("Unsupported plot value type"),
|
|
}
|
|
}
|
|
|
|
pub const PlotType = enum(c_int) {
|
|
Number,
|
|
Memory,
|
|
Percentage,
|
|
Watt,
|
|
};
|
|
|
|
pub const PlotConfig = struct {
|
|
plot_type: PlotType,
|
|
step: c_int,
|
|
fill: c_int,
|
|
color: u32,
|
|
};
|
|
|
|
pub inline fn plotConfig(comptime name: [:0]const u8, comptime config: PlotConfig) void {
|
|
if (!options.tracy_enable) return;
|
|
c.___tracy_emit_plot_config(
|
|
name,
|
|
@intFromEnum(config.plot_type),
|
|
config.step,
|
|
config.fill,
|
|
config.color,
|
|
);
|
|
}
|
|
|
|
pub inline fn message(comptime msg: [:0]const u8) void {
|
|
if (!options.tracy_enable) return;
|
|
const depth = options.tracy_callstack orelse 0;
|
|
c.___tracy_emit_messageL(msg, depth);
|
|
}
|
|
|
|
pub inline fn messageColor(comptime msg: [:0]const u8, color: u32) void {
|
|
if (!options.tracy_enable) return;
|
|
const depth = options.tracy_callstack orelse 0;
|
|
c.___tracy_emit_messageLC(msg, color, depth);
|
|
}
|
|
|
|
const tracy_message_buffer_size = if (options.tracy_enable) 4096 else 0;
|
|
threadlocal var tracy_message_buffer: [tracy_message_buffer_size]u8 = undefined;
|
|
|
|
pub inline fn print(comptime fmt: []const u8, args: anytype) void {
|
|
if (!options.tracy_enable) return;
|
|
const depth = options.tracy_callstack orelse 0;
|
|
|
|
var stream = std.io.fixedBufferStream(&tracy_message_buffer);
|
|
stream.writer().print(fmt, args) catch {};
|
|
|
|
const written = stream.getWritten();
|
|
c.___tracy_emit_message(written.ptr, written.len, depth);
|
|
}
|
|
|
|
pub inline fn printColor(comptime fmt: []const u8, args: anytype, color: u32) void {
|
|
if (!options.tracy_enable) return;
|
|
const depth = options.tracy_callstack orelse 0;
|
|
|
|
var stream = std.io.fixedBufferStream(&tracy_message_buffer);
|
|
stream.writer().print(fmt, args) catch {};
|
|
|
|
const written = stream.getWritten();
|
|
c.___tracy_emit_messageC(written.ptr, written.len, color, depth);
|
|
}
|
|
|
|
pub inline fn printAppInfo(comptime fmt: []const u8, args: anytype) void {
|
|
if (!options.tracy_enable) return;
|
|
|
|
var stream = std.io.fixedBufferStream(&tracy_message_buffer);
|
|
stream.reset();
|
|
stream.writer().print(fmt, args) catch {};
|
|
|
|
const written = stream.getWritten();
|
|
c.___tracy_emit_message_appinfo(written.ptr, written.len);
|
|
}
|
|
|
|
pub const TracingAllocator = struct {
|
|
parent_allocator: std.mem.Allocator,
|
|
pool_name: ?[:0]const u8,
|
|
|
|
const Self = @This();
|
|
|
|
pub fn init(parent_allocator: std.mem.Allocator) Self {
|
|
return .{
|
|
.parent_allocator = parent_allocator,
|
|
.pool_name = null,
|
|
};
|
|
}
|
|
|
|
pub fn initNamed(comptime pool_name: [:0]const u8, parent_allocator: std.mem.Allocator) Self {
|
|
return .{
|
|
.parent_allocator = parent_allocator,
|
|
.pool_name = pool_name,
|
|
};
|
|
}
|
|
|
|
pub fn allocator(self: *Self) std.mem.Allocator {
|
|
return .{
|
|
.ptr = self,
|
|
.vtable = &.{
|
|
.alloc = alloc,
|
|
.resize = resize,
|
|
.remap = remap,
|
|
.free = free,
|
|
},
|
|
};
|
|
}
|
|
|
|
fn alloc(
|
|
ctx: *anyopaque,
|
|
len: usize,
|
|
ptr_align: std.mem.Alignment,
|
|
ret_addr: usize,
|
|
) ?[*]u8 {
|
|
const self: *Self = @ptrCast(@alignCast(ctx));
|
|
const result = self.parent_allocator.rawAlloc(len, ptr_align, ret_addr);
|
|
if (!options.tracy_enable) return result;
|
|
|
|
if (self.pool_name) |name| {
|
|
c.___tracy_emit_memory_alloc_named(result, len, 0, name.ptr);
|
|
} else {
|
|
c.___tracy_emit_memory_alloc(result, len, 0);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
fn resize(
|
|
ctx: *anyopaque,
|
|
buf: []u8,
|
|
buf_align: std.mem.Alignment,
|
|
new_len: usize,
|
|
ret_addr: usize,
|
|
) bool {
|
|
const self: *Self = @ptrCast(@alignCast(ctx));
|
|
const result = self.parent_allocator.rawResize(buf, buf_align, new_len, ret_addr);
|
|
if (!result) return false;
|
|
|
|
if (!options.tracy_enable) return true;
|
|
|
|
if (self.pool_name) |name| {
|
|
c.___tracy_emit_memory_free_named(buf.ptr, 0, name.ptr);
|
|
c.___tracy_emit_memory_alloc_named(buf.ptr, new_len, 0, name.ptr);
|
|
} else {
|
|
c.___tracy_emit_memory_free(buf.ptr, 0);
|
|
c.___tracy_emit_memory_alloc(buf.ptr, new_len, 0);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
fn remap(
|
|
ctx: *anyopaque,
|
|
buf: []u8,
|
|
buf_align: std.mem.Alignment,
|
|
new_len: usize,
|
|
ret_addr: usize,
|
|
) ?[*]u8 {
|
|
const self: *Self = @ptrCast(@alignCast(ctx));
|
|
const result = self.parent_allocator.rawRemap(buf, buf_align, new_len, ret_addr);
|
|
const new_buf = result orelse return null;
|
|
|
|
if (!options.tracy_enable) return new_buf;
|
|
|
|
if (self.pool_name) |name| {
|
|
c.___tracy_emit_memory_free_named(buf.ptr, 0, name.ptr);
|
|
c.___tracy_emit_memory_alloc_named(new_buf, new_len, 0, name.ptr);
|
|
} else {
|
|
c.___tracy_emit_memory_free(buf.ptr, 0);
|
|
c.___tracy_emit_memory_alloc(new_buf, new_len, 0);
|
|
}
|
|
|
|
return new_buf;
|
|
}
|
|
|
|
fn free(
|
|
ctx: *anyopaque,
|
|
buf: []u8,
|
|
buf_align: std.mem.Alignment,
|
|
ret_addr: usize,
|
|
) void {
|
|
const self: *Self = @ptrCast(@alignCast(ctx));
|
|
|
|
if (options.tracy_enable) {
|
|
if (self.pool_name) |name| {
|
|
c.___tracy_emit_memory_free_named(buf.ptr, 0, name.ptr);
|
|
} else {
|
|
c.___tracy_emit_memory_free(buf.ptr, 0);
|
|
}
|
|
}
|
|
|
|
self.parent_allocator.rawFree(buf, buf_align, ret_addr);
|
|
}
|
|
};
|