aboutsummaryrefslogtreecommitdiff
path: root/vendor/libghostty-vt/src/renderer/Metal.zig
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-09-10 21:51:57 +0300
committerGitHub <noreply@github.com>2026-09-10 21:51:57 +0300
commit425c86179791cd32e2d4ce0ae7f269940b4b0663 (patch)
treee52c4383a6d69216cbe2a32638bf90841d7e2189 /vendor/libghostty-vt/src/renderer/Metal.zig
parent90e947a6e26e02f10ec7f1694c4eb5b78a86406b (diff)
chore: upgrade libghostty and preserve terminal behavior (#3906)
Diffstat (limited to 'vendor/libghostty-vt/src/renderer/Metal.zig')
-rw-r--r--vendor/libghostty-vt/src/renderer/Metal.zig38
1 files changed, 38 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/src/renderer/Metal.zig b/vendor/libghostty-vt/src/renderer/Metal.zig
index 6c7432d2..9247454d 100644
--- a/vendor/libghostty-vt/src/renderer/Metal.zig
+++ b/vendor/libghostty-vt/src/renderer/Metal.zig
@@ -407,6 +407,44 @@ pub inline fn beginFrame(
return try Frame.begin(.{ .queue = self.queue }, renderer, target);
}
+/// Warm up the Metal device machinery. The first Metal device query in
+/// a process takes multiple milliseconds; once warm, subsequent queries
+/// are effectively free. Calling this early (e.g. on a background
+/// thread at app startup; Metal device queries are thread-safe) moves
+/// that one-time cost off the critical path of the first surface's
+/// renderer initialization.
+pub fn warmup() void {
+ const device = chooseDevice() catch return;
+ defer device.release();
+
+ // Create and release a command queue. The first command queue
+ // created for a device pays additional one-time driver setup
+ // costs; subsequent creations are much cheaper.
+ const queue = device.msgSend(objc.Object, objc.sel("newCommandQueue"), .{});
+ queue.release();
+
+ // Build and discard our shader pipelines for both pixel formats we
+ // may use (which one is used depends on the blending config). The
+ // first pipeline state creation compiles shaders which is slow;
+ // once warm, later creations hit driver and OS caches.
+ inline for (.{
+ mtl.MTLPixelFormat.bgra8unorm_srgb,
+ mtl.MTLPixelFormat.bgra8unorm,
+ }) |format| {
+ if (shaders.Shaders.init(
+ std.heap.c_allocator,
+ device,
+ &.{},
+ format,
+ )) |s| {
+ var s_mut = s;
+ s_mut.deinit(std.heap.c_allocator);
+ } else |err| {
+ log.warn("metal warmup shader init failed err={}", .{err});
+ }
+ }
+}
+
fn chooseDevice() error{NoMetalDevice}!objc.Object {
var chosen_device: ?objc.Object = null;