| ... | @@ -2,47 +2,308 @@ const std = @import("std"); | ... | @@ -2,47 +2,308 @@ const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | | 3 | |
| 4 | pub const enable = if (builtin.is_test) false else @import("build_options").enable_tracy; | 4 | pub const enable = if (builtin.is_test) false else @import("build_options").enable_tracy; |
| | 5 | const enable_callstack = @import("build_options").enable_tracy_callstack; |
| 5 | | 6 | |
| 6 | extern fn ___tracy_emit_zone_begin_callstack( | 7 | // TODO: make this configurable |
| 7 | srcloc: *const ___tracy_source_location_data, | 8 | const callstack_depth = 10; |
| 8 | depth: c_int, | | |
| 9 | active: c_int, | | |
| 10 | ) ___tracy_c_zone_context; | | |
| 11 | | | |
| 12 | extern fn ___tracy_emit_zone_end(ctx: ___tracy_c_zone_context) void; | | |
| 13 | | | |
| 14 | pub const ___tracy_source_location_data = extern struct { | | |
| 15 | name: ?[*:0]const u8, | | |
| 16 | function: [*:0]const u8, | | |
| 17 | file: [*:0]const u8, | | |
| 18 | line: u32, | | |
| 19 | color: u32, | | |
| 20 | }; | | |
| 21 | | 9 | |
| 22 | pub const ___tracy_c_zone_context = extern struct { | 10 | const ___tracy_c_zone_context = extern struct { |
| 23 | id: u32, | 11 | id: u32, |
| 24 | active: c_int, | 12 | active: c_int, |
| 25 | | 13 | |
| 26 | pub fn end(self: ___tracy_c_zone_context) void { | 14 | pub inline fn end(self: @This()) void { |
| 27 | ___tracy_emit_zone_end(self); | 15 | ___tracy_emit_zone_end(self); |
| 28 | } | 16 | } |
| | 17 | |
| | 18 | pub inline fn addText(self: @This(), text: []const u8) void { |
| | 19 | ___tracy_emit_zone_text(self, text.ptr, text.len); |
| | 20 | } |
| | 21 | |
| | 22 | pub inline fn setName(self: @This(), name: []const u8) void { |
| | 23 | ___tracy_emit_zone_name(self, name.ptr, name.len); |
| | 24 | } |
| | 25 | |
| | 26 | pub inline fn setColor(self: @This(), color: u32) void { |
| | 27 | ___tracy_emit_zone_color(self, color); |
| | 28 | } |
| | 29 | |
| | 30 | pub inline fn setValue(self: @This(), value: u64) void { |
| | 31 | ___tracy_emit_zone_value(self, value); |
| | 32 | } |
| 29 | }; | 33 | }; |
| 30 | | 34 | |
| 31 | pub const Ctx = if (enable) ___tracy_c_zone_context else struct { | 35 | pub const Ctx = if (enable) ___tracy_c_zone_context else struct { |
| 32 | pub fn end(self: Ctx) void { | 36 | pub inline fn end(self: @This()) void { |
| | 37 | _ = self; |
| | 38 | } |
| | 39 | |
| | 40 | pub inline fn addText(self: @This(), text: []const u8) void { |
| 33 | _ = self; | 41 | _ = self; |
| | 42 | _ = text; |
| | 43 | } |
| | 44 | |
| | 45 | pub inline fn setName(self: @This(), name: []const u8) void { |
| | 46 | _ = self; |
| | 47 | _ = name; |
| | 48 | } |
| | 49 | |
| | 50 | pub inline fn setColor(self: @This(), color: u32) void { |
| | 51 | _ = self; |
| | 52 | _ = color; |
| | 53 | } |
| | 54 | |
| | 55 | pub inline fn setValue(self: @This(), value: u64) void { |
| | 56 | _ = self; |
| | 57 | _ = value; |
| 34 | } | 58 | } |
| 35 | }; | 59 | }; |
| 36 | | 60 | |
| 37 | pub inline fn trace(comptime src: std.builtin.SourceLocation) Ctx { | 61 | pub inline fn trace(comptime src: std.builtin.SourceLocation) Ctx { |
| 38 | if (!enable) return .{}; | 62 | if (!enable) return .{}; |
| 39 | | 63 | |
| 40 | const loc: ___tracy_source_location_data = .{ | 64 | if (enable_callstack) { |
| 41 | .name = null, | 65 | return ___tracy_emit_zone_begin_callstack(&.{ |
| 42 | .function = src.fn_name.ptr, | 66 | .name = null, |
| 43 | .file = src.file.ptr, | 67 | .function = src.fn_name.ptr, |
| 44 | .line = src.line, | 68 | .file = src.file.ptr, |
| 45 | .color = 0, | 69 | .line = src.line, |
| | 70 | .color = 0, |
| | 71 | }, callstack_depth, 1); |
| | 72 | } else { |
| | 73 | return ___tracy_emit_zone_begin(&.{ |
| | 74 | .name = null, |
| | 75 | .function = src.fn_name.ptr, |
| | 76 | .file = src.file.ptr, |
| | 77 | .line = src.line, |
| | 78 | .color = 0, |
| | 79 | }, 1); |
| | 80 | } |
| | 81 | } |
| | 82 | |
| | 83 | pub inline fn traceNamed(comptime src: std.builtin.SourceLocation, comptime name: [:0]const u8) Ctx { |
| | 84 | if (!enable) return .{}; |
| | 85 | |
| | 86 | if (enable_callstack) { |
| | 87 | return ___tracy_emit_zone_begin_callstack(&.{ |
| | 88 | .name = name.ptr, |
| | 89 | .function = src.fn_name.ptr, |
| | 90 | .file = src.file.ptr, |
| | 91 | .line = src.line, |
| | 92 | .color = 0, |
| | 93 | }, callstack_depth, 1); |
| | 94 | } else { |
| | 95 | return ___tracy_emit_zone_begin(&.{ |
| | 96 | .name = name.ptr, |
| | 97 | .function = src.fn_name.ptr, |
| | 98 | .file = src.file.ptr, |
| | 99 | .line = src.line, |
| | 100 | .color = 0, |
| | 101 | }, 1); |
| | 102 | } |
| | 103 | } |
| | 104 | |
| | 105 | pub fn tracyAllocator(allocator: *std.mem.Allocator) TracyAllocator(null) { |
| | 106 | return TracyAllocator(null).init(allocator); |
| | 107 | } |
| | 108 | |
| | 109 | pub fn TracyAllocator(comptime name: ?[:0]const u8) type { |
| | 110 | return struct { |
| | 111 | allocator: std.mem.Allocator, |
| | 112 | parent_allocator: *std.mem.Allocator, |
| | 113 | |
| | 114 | const Self = @This(); |
| | 115 | |
| | 116 | pub fn init(allocator: *std.mem.Allocator) Self { |
| | 117 | return .{ |
| | 118 | .parent_allocator = allocator, |
| | 119 | .allocator = .{ |
| | 120 | .allocFn = allocFn, |
| | 121 | .resizeFn = resizeFn, |
| | 122 | }, |
| | 123 | }; |
| | 124 | } |
| | 125 | |
| | 126 | fn allocFn(allocator: *std.mem.Allocator, len: usize, ptr_align: u29, len_align: u29, ret_addr: usize) std.mem.Allocator.Error![]u8 { |
| | 127 | const self = @fieldParentPtr(Self, "allocator", allocator); |
| | 128 | const result = self.parent_allocator.allocFn(self.parent_allocator, len, ptr_align, len_align, ret_addr); |
| | 129 | if (result) |data| { |
| | 130 | if (data.len != 0) { |
| | 131 | if (name) |n| { |
| | 132 | allocNamed(data.ptr, data.len, n); |
| | 133 | } else { |
| | 134 | alloc(data.ptr, data.len); |
| | 135 | } |
| | 136 | } |
| | 137 | } else |_| { |
| | 138 | messageColor("allocation failed", 0xFF0000); |
| | 139 | } |
| | 140 | return result; |
| | 141 | } |
| | 142 | |
| | 143 | fn resizeFn(allocator: *std.mem.Allocator, buf: []u8, buf_align: u29, new_len: usize, len_align: u29, ret_addr: usize) std.mem.Allocator.Error!usize { |
| | 144 | const self = @fieldParentPtr(Self, "allocator", allocator); |
| | 145 | |
| | 146 | if (self.parent_allocator.resizeFn(self.parent_allocator, buf, buf_align, new_len, len_align, ret_addr)) |resized_len| { |
| | 147 | // this condition is to handle free being called on an empty slice that was never even allocated |
| | 148 | // example case: `std.process.getSelfExeSharedLibPaths` can return `&[_][:0]u8{}` |
| | 149 | if (buf.len != 0) { |
| | 150 | if (name) |n| { |
| | 151 | freeNamed(buf.ptr, n); |
| | 152 | } else { |
| | 153 | free(buf.ptr); |
| | 154 | } |
| | 155 | } |
| | 156 | |
| | 157 | if (resized_len != 0) { |
| | 158 | // this was a shrink or a resize |
| | 159 | if (name) |n| { |
| | 160 | allocNamed(buf.ptr, resized_len, n); |
| | 161 | } else { |
| | 162 | alloc(buf.ptr, resized_len); |
| | 163 | } |
| | 164 | } |
| | 165 | |
| | 166 | return resized_len; |
| | 167 | } else |err| { |
| | 168 | // this is not really an error condition, during normal operation the compiler hits this case thousands of times |
| | 169 | // due to this emitting messages for it is both slow and causes clutter |
| | 170 | // messageColor("allocation resize failed", 0xFF0000); |
| | 171 | return err; |
| | 172 | } |
| | 173 | } |
| | 174 | }; |
| | 175 | } |
| | 176 | |
| | 177 | // This function only accepts comptime known strings, see `messageCopy` for runtime strings |
| | 178 | pub inline fn message(comptime msg: [:0]const u8) void { |
| | 179 | if (!enable) return; |
| | 180 | ___tracy_emit_messageL(msg.ptr, if (enable_callstack) callstack_depth else 0); |
| | 181 | } |
| | 182 | |
| | 183 | // This function only accepts comptime known strings, see `messageColorCopy` for runtime strings |
| | 184 | pub inline fn messageColor(comptime msg: [:0]const u8, color: u32) void { |
| | 185 | if (!enable) return; |
| | 186 | ___tracy_emit_messageLC(msg.ptr, color, if (enable_callstack) callstack_depth else 0); |
| | 187 | } |
| | 188 | |
| | 189 | pub inline fn messageCopy(msg: []const u8) void { |
| | 190 | if (!enable) return; |
| | 191 | ___tracy_emit_message(msg.ptr, msg.len, if (enable_callstack) callstack_depth else 0); |
| | 192 | } |
| | 193 | |
| | 194 | pub inline fn messageColorCopy(msg: [:0]const u8, color: u32) void { |
| | 195 | if (!enable) return; |
| | 196 | ___tracy_emit_messageC(msg.ptr, msg.len, color, if (enable_callstack) callstack_depth else 0); |
| | 197 | } |
| | 198 | |
| | 199 | pub inline fn frameMark() void { |
| | 200 | if (!enable) return; |
| | 201 | ___tracy_emit_frame_mark(null); |
| | 202 | } |
| | 203 | |
| | 204 | pub inline fn frameMarkNamed(comptime name: [:0]const u8) void { |
| | 205 | if (!enable) return; |
| | 206 | ___tracy_emit_frame_mark(name.ptr); |
| | 207 | } |
| | 208 | |
| | 209 | pub inline fn namedFrame(comptime name: [:0]const u8) Frame(name) { |
| | 210 | frameMarkStart(name); |
| | 211 | return .{}; |
| | 212 | } |
| | 213 | |
| | 214 | pub fn Frame(comptime name: [:0]const u8) type { |
| | 215 | return struct { |
| | 216 | pub fn end(_: @This()) void { |
| | 217 | frameMarkEnd(name); |
| | 218 | } |
| 46 | }; | 219 | }; |
| 47 | return ___tracy_emit_zone_begin_callstack(&loc, 1, 1); | | |
| 48 | } | 220 | } |
| | 221 | |
| | 222 | inline fn frameMarkStart(comptime name: [:0]const u8) void { |
| | 223 | if (!enable) return; |
| | 224 | ___tracy_emit_frame_mark_start(name.ptr); |
| | 225 | } |
| | 226 | |
| | 227 | inline fn frameMarkEnd(comptime name: [:0]const u8) void { |
| | 228 | if (!enable) return; |
| | 229 | ___tracy_emit_frame_mark_end(name.ptr); |
| | 230 | } |
| | 231 | |
| | 232 | extern fn ___tracy_emit_frame_mark_start(name: [*:0]const u8) void; |
| | 233 | extern fn ___tracy_emit_frame_mark_end(name: [*:0]const u8) void; |
| | 234 | |
| | 235 | inline fn alloc(ptr: [*]u8, len: usize) void { |
| | 236 | if (!enable) return; |
| | 237 | |
| | 238 | if (enable_callstack) { |
| | 239 | ___tracy_emit_memory_alloc_callstack(ptr, len, callstack_depth, 0); |
| | 240 | } else { |
| | 241 | ___tracy_emit_memory_alloc(ptr, len, 0); |
| | 242 | } |
| | 243 | } |
| | 244 | |
| | 245 | inline fn allocNamed(ptr: [*]u8, len: usize, comptime name: [:0]const u8) void { |
| | 246 | if (!enable) return; |
| | 247 | |
| | 248 | if (enable_callstack) { |
| | 249 | ___tracy_emit_memory_alloc_callstack_named(ptr, len, callstack_depth, 0, name.ptr); |
| | 250 | } else { |
| | 251 | ___tracy_emit_memory_alloc_named(ptr, len, 0, name.ptr); |
| | 252 | } |
| | 253 | } |
| | 254 | |
| | 255 | inline fn free(ptr: [*]u8) void { |
| | 256 | if (!enable) return; |
| | 257 | |
| | 258 | if (enable_callstack) { |
| | 259 | ___tracy_emit_memory_free_callstack(ptr, callstack_depth, 0); |
| | 260 | } else { |
| | 261 | ___tracy_emit_memory_free(ptr, 0); |
| | 262 | } |
| | 263 | } |
| | 264 | |
| | 265 | inline fn freeNamed(ptr: [*]u8, comptime name: [:0]const u8) void { |
| | 266 | if (!enable) return; |
| | 267 | |
| | 268 | if (enable_callstack) { |
| | 269 | ___tracy_emit_memory_free_callstack_named(ptr, callstack_depth, 0, name.ptr); |
| | 270 | } else { |
| | 271 | ___tracy_emit_memory_free_named(ptr, 0, name.ptr); |
| | 272 | } |
| | 273 | } |
| | 274 | |
| | 275 | extern fn ___tracy_emit_zone_begin( |
| | 276 | srcloc: *const ___tracy_source_location_data, |
| | 277 | active: c_int, |
| | 278 | ) ___tracy_c_zone_context; |
| | 279 | extern fn ___tracy_emit_zone_begin_callstack( |
| | 280 | srcloc: *const ___tracy_source_location_data, |
| | 281 | depth: c_int, |
| | 282 | active: c_int, |
| | 283 | ) ___tracy_c_zone_context; |
| | 284 | extern fn ___tracy_emit_zone_text(ctx: ___tracy_c_zone_context, txt: [*]const u8, size: usize) void; |
| | 285 | extern fn ___tracy_emit_zone_name(ctx: ___tracy_c_zone_context, txt: [*]const u8, size: usize) void; |
| | 286 | extern fn ___tracy_emit_zone_color(ctx: ___tracy_c_zone_context, color: u32) void; |
| | 287 | extern fn ___tracy_emit_zone_value(ctx: ___tracy_c_zone_context, value: u64) void; |
| | 288 | extern fn ___tracy_emit_zone_end(ctx: ___tracy_c_zone_context) void; |
| | 289 | extern fn ___tracy_emit_memory_alloc(ptr: *const c_void, size: usize, secure: c_int) void; |
| | 290 | extern fn ___tracy_emit_memory_alloc_callstack(ptr: *const c_void, size: usize, depth: c_int, secure: c_int) void; |
| | 291 | extern fn ___tracy_emit_memory_free(ptr: *const c_void, secure: c_int) void; |
| | 292 | extern fn ___tracy_emit_memory_free_callstack(ptr: *const c_void, depth: c_int, secure: c_int) void; |
| | 293 | extern fn ___tracy_emit_memory_alloc_named(ptr: *const c_void, size: usize, secure: c_int, name: [*:0]const u8) void; |
| | 294 | extern fn ___tracy_emit_memory_alloc_callstack_named(ptr: *const c_void, size: usize, depth: c_int, secure: c_int, name: [*:0]const u8) void; |
| | 295 | extern fn ___tracy_emit_memory_free_named(ptr: *const c_void, secure: c_int, name: [*:0]const u8) void; |
| | 296 | extern fn ___tracy_emit_memory_free_callstack_named(ptr: *const c_void, depth: c_int, secure: c_int, name: [*:0]const u8) void; |
| | 297 | extern fn ___tracy_emit_message(txt: [*]const u8, size: usize, callstack: c_int) void; |
| | 298 | extern fn ___tracy_emit_messageL(txt: [*:0]const u8, callstack: c_int) void; |
| | 299 | extern fn ___tracy_emit_messageC(txt: [*]const u8, size: usize, color: u32, callstack: c_int) void; |
| | 300 | extern fn ___tracy_emit_messageLC(txt: [*:0]const u8, color: u32, callstack: c_int) void; |
| | 301 | extern fn ___tracy_emit_frame_mark(name: ?[*:0]const u8) void; |
| | 302 | |
| | 303 | const ___tracy_source_location_data = extern struct { |
| | 304 | name: ?[*:0]const u8, |
| | 305 | function: [*:0]const u8, |
| | 306 | file: [*:0]const u8, |
| | 307 | line: u32, |
| | 308 | color: u32, |
| | 309 | }; |