mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 16:56:09 +03:00
renderer/metal: move more metal objects into GPUState
This commit is contained in:
@ -108,11 +108,8 @@ image_text_end: u32 = 0,
|
|||||||
|
|
||||||
/// Metal state
|
/// Metal state
|
||||||
shaders: Shaders, // Compiled shaders
|
shaders: Shaders, // Compiled shaders
|
||||||
buf_instance: InstanceBuffer, // MTLBuffer
|
|
||||||
|
|
||||||
/// Metal objects
|
/// Metal objects
|
||||||
device: objc.Object, // MTLDevice
|
|
||||||
queue: objc.Object, // MTLCommandQueue
|
|
||||||
layer: objc.Object, // CAMetalLayer
|
layer: objc.Object, // CAMetalLayer
|
||||||
|
|
||||||
/// Custom shader state. This is only set if we have custom shaders.
|
/// Custom shader state. This is only set if we have custom shaders.
|
||||||
@ -141,10 +138,26 @@ pub const GPUState = struct {
|
|||||||
frame_sema: std.Thread.Semaphore = .{ .permits = BufferCount },
|
frame_sema: std.Thread.Semaphore = .{ .permits = BufferCount },
|
||||||
|
|
||||||
device: objc.Object, // MTLDevice
|
device: objc.Object, // MTLDevice
|
||||||
|
queue: objc.Object, // MTLCommandQueue
|
||||||
|
|
||||||
|
/// This buffer is written exactly once so we can use it globally.
|
||||||
|
instance: InstanceBuffer, // MTLBuffer
|
||||||
|
|
||||||
pub fn init() !GPUState {
|
pub fn init() !GPUState {
|
||||||
|
const device = objc.Object.fromId(mtl.MTLCreateSystemDefaultDevice());
|
||||||
|
const queue = device.msgSend(objc.Object, objc.sel("newCommandQueue"), .{});
|
||||||
|
errdefer queue.msgSend(void, objc.sel("release"), .{});
|
||||||
|
|
||||||
|
var instance = try InstanceBuffer.initFill(device, &.{
|
||||||
|
0, 1, 3, // Top-left triangle
|
||||||
|
1, 2, 3, // Bottom-right triangle
|
||||||
|
});
|
||||||
|
errdefer instance.deinit();
|
||||||
|
|
||||||
var result: GPUState = .{
|
var result: GPUState = .{
|
||||||
.device = objc.Object.fromId(mtl.MTLCreateSystemDefaultDevice()),
|
.device = device,
|
||||||
|
.queue = queue,
|
||||||
|
.instance = instance,
|
||||||
.frames = undefined,
|
.frames = undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -161,6 +174,8 @@ pub const GPUState = struct {
|
|||||||
// we can cleanly deinit our GPU state.
|
// we can cleanly deinit our GPU state.
|
||||||
for (0..BufferCount) |_| self.frame_sema.wait();
|
for (0..BufferCount) |_| self.frame_sema.wait();
|
||||||
for (&self.frames) |*frame| frame.deinit();
|
for (&self.frames) |*frame| frame.deinit();
|
||||||
|
self.instance.deinit();
|
||||||
|
self.queue.msgSend(void, objc.sel("release"), .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the next frame state to draw to. This will wait on the
|
/// Get the next frame state to draw to. This will wait on the
|
||||||
@ -423,8 +438,8 @@ pub fn init(alloc: Allocator, options: renderer.Options) !Metal {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Initialize our metal stuff
|
// Initialize our metal stuff
|
||||||
const device = objc.Object.fromId(mtl.MTLCreateSystemDefaultDevice());
|
var gpu_state = try GPUState.init();
|
||||||
const queue = device.msgSend(objc.Object, objc.sel("newCommandQueue"), .{});
|
errdefer gpu_state.deinit();
|
||||||
|
|
||||||
// Get our CAMetalLayer
|
// Get our CAMetalLayer
|
||||||
const layer = switch (builtin.os.tag) {
|
const layer = switch (builtin.os.tag) {
|
||||||
@ -438,7 +453,7 @@ pub fn init(alloc: Allocator, options: renderer.Options) !Metal {
|
|||||||
|
|
||||||
else => @compileError("unsupported target for Metal"),
|
else => @compileError("unsupported target for Metal"),
|
||||||
};
|
};
|
||||||
layer.setProperty("device", device.value);
|
layer.setProperty("device", gpu_state.device.value);
|
||||||
layer.setProperty("opaque", options.config.background_opacity >= 1);
|
layer.setProperty("opaque", options.config.background_opacity >= 1);
|
||||||
layer.setProperty("displaySyncEnabled", false); // disable v-sync
|
layer.setProperty("displaySyncEnabled", false); // disable v-sync
|
||||||
|
|
||||||
@ -467,13 +482,6 @@ pub fn init(alloc: Allocator, options: renderer.Options) !Metal {
|
|||||||
});
|
});
|
||||||
errdefer font_shaper.deinit();
|
errdefer font_shaper.deinit();
|
||||||
|
|
||||||
// Vertex buffers
|
|
||||||
var buf_instance = try InstanceBuffer.initFill(device, &.{
|
|
||||||
0, 1, 3, // Top-left triangle
|
|
||||||
1, 2, 3, // Bottom-right triangle
|
|
||||||
});
|
|
||||||
errdefer buf_instance.deinit();
|
|
||||||
|
|
||||||
// Load our custom shaders
|
// Load our custom shaders
|
||||||
const custom_shaders: []const [:0]const u8 = shadertoy.loadFromFiles(
|
const custom_shaders: []const [:0]const u8 = shadertoy.loadFromFiles(
|
||||||
arena_alloc,
|
arena_alloc,
|
||||||
@ -489,7 +497,7 @@ pub fn init(alloc: Allocator, options: renderer.Options) !Metal {
|
|||||||
if (custom_shaders.len == 0) break :state null;
|
if (custom_shaders.len == 0) break :state null;
|
||||||
|
|
||||||
// Build our sampler for our texture
|
// Build our sampler for our texture
|
||||||
var sampler = try mtl_sampler.Sampler.init(device);
|
var sampler = try mtl_sampler.Sampler.init(gpu_state.device);
|
||||||
errdefer sampler.deinit();
|
errdefer sampler.deinit();
|
||||||
|
|
||||||
break :state .{
|
break :state .{
|
||||||
@ -517,7 +525,7 @@ pub fn init(alloc: Allocator, options: renderer.Options) !Metal {
|
|||||||
errdefer if (custom_shader_state) |*state| state.deinit();
|
errdefer if (custom_shader_state) |*state| state.deinit();
|
||||||
|
|
||||||
// Initialize our shaders
|
// Initialize our shaders
|
||||||
var shaders = try Shaders.init(alloc, device, custom_shaders);
|
var shaders = try Shaders.init(alloc, gpu_state.device, custom_shaders);
|
||||||
errdefer shaders.deinit(alloc);
|
errdefer shaders.deinit(alloc);
|
||||||
|
|
||||||
// Initialize all the data that requires a critical font section.
|
// Initialize all the data that requires a critical font section.
|
||||||
@ -532,10 +540,6 @@ pub fn init(alloc: Allocator, options: renderer.Options) !Metal {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Build our GPU state
|
|
||||||
var gpu_state = try GPUState.init();
|
|
||||||
errdefer gpu_state.deinit();
|
|
||||||
|
|
||||||
return Metal{
|
return Metal{
|
||||||
.alloc = alloc,
|
.alloc = alloc,
|
||||||
.config = options.config,
|
.config = options.config,
|
||||||
@ -564,11 +568,8 @@ pub fn init(alloc: Allocator, options: renderer.Options) !Metal {
|
|||||||
|
|
||||||
// Shaders
|
// Shaders
|
||||||
.shaders = shaders,
|
.shaders = shaders,
|
||||||
.buf_instance = buf_instance,
|
|
||||||
|
|
||||||
// Metal stuff
|
// Metal stuff
|
||||||
.device = device,
|
|
||||||
.queue = queue,
|
|
||||||
.layer = layer,
|
.layer = layer,
|
||||||
.custom_shader_state = custom_shader_state,
|
.custom_shader_state = custom_shader_state,
|
||||||
.gpu_state = gpu_state,
|
.gpu_state = gpu_state,
|
||||||
@ -592,9 +593,6 @@ pub fn deinit(self: *Metal) void {
|
|||||||
}
|
}
|
||||||
self.image_placements.deinit(self.alloc);
|
self.image_placements.deinit(self.alloc);
|
||||||
|
|
||||||
self.buf_instance.deinit();
|
|
||||||
self.queue.msgSend(void, objc.sel("release"), .{});
|
|
||||||
|
|
||||||
if (self.custom_shader_state) |*state| state.deinit();
|
if (self.custom_shader_state) |*state| state.deinit();
|
||||||
|
|
||||||
self.shaders.deinit(self.alloc);
|
self.shaders.deinit(self.alloc);
|
||||||
@ -797,7 +795,7 @@ pub fn updateFrame(
|
|||||||
.replace_grey_alpha,
|
.replace_grey_alpha,
|
||||||
.replace_rgb,
|
.replace_rgb,
|
||||||
.replace_rgba,
|
.replace_rgba,
|
||||||
=> try kv.value_ptr.image.upload(self.alloc, self.device),
|
=> try kv.value_ptr.image.upload(self.alloc, self.gpu_state.device),
|
||||||
|
|
||||||
.unload_pending,
|
.unload_pending,
|
||||||
.unload_replace,
|
.unload_replace,
|
||||||
@ -858,7 +856,7 @@ pub fn drawFrame(self: *Metal, surface: *apprt.Surface) !void {
|
|||||||
self.font_grid.lock.lockShared();
|
self.font_grid.lock.lockShared();
|
||||||
defer self.font_grid.lock.unlockShared();
|
defer self.font_grid.lock.unlockShared();
|
||||||
frame.greyscale_modified = self.font_grid.atlas_greyscale.modified.load(.monotonic);
|
frame.greyscale_modified = self.font_grid.atlas_greyscale.modified.load(.monotonic);
|
||||||
try syncAtlasTexture(self.device, &self.font_grid.atlas_greyscale, &frame.greyscale);
|
try syncAtlasTexture(self.gpu_state.device, &self.font_grid.atlas_greyscale, &frame.greyscale);
|
||||||
}
|
}
|
||||||
texture: {
|
texture: {
|
||||||
const modified = self.font_grid.atlas_color.modified.load(.monotonic);
|
const modified = self.font_grid.atlas_color.modified.load(.monotonic);
|
||||||
@ -866,11 +864,11 @@ pub fn drawFrame(self: *Metal, surface: *apprt.Surface) !void {
|
|||||||
self.font_grid.lock.lockShared();
|
self.font_grid.lock.lockShared();
|
||||||
defer self.font_grid.lock.unlockShared();
|
defer self.font_grid.lock.unlockShared();
|
||||||
frame.color_modified = self.font_grid.atlas_color.modified.load(.monotonic);
|
frame.color_modified = self.font_grid.atlas_color.modified.load(.monotonic);
|
||||||
try syncAtlasTexture(self.device, &self.font_grid.atlas_color, &frame.color);
|
try syncAtlasTexture(self.gpu_state.device, &self.font_grid.atlas_color, &frame.color);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Command buffer (MTLCommandBuffer)
|
// Command buffer (MTLCommandBuffer)
|
||||||
const buffer = self.queue.msgSend(objc.Object, objc.sel("commandBuffer"), .{});
|
const buffer = self.gpu_state.queue.msgSend(objc.Object, objc.sel("commandBuffer"), .{});
|
||||||
|
|
||||||
{
|
{
|
||||||
// MTLRenderPassDescriptor
|
// MTLRenderPassDescriptor
|
||||||
@ -1150,7 +1148,7 @@ fn drawImagePlacement(
|
|||||||
// Create our vertex buffer, which is always exactly one item.
|
// Create our vertex buffer, which is always exactly one item.
|
||||||
// future(mitchellh): we can group rendering multiple instances of a single image
|
// future(mitchellh): we can group rendering multiple instances of a single image
|
||||||
const Buffer = mtl_buffer.Buffer(mtl_shaders.Image);
|
const Buffer = mtl_buffer.Buffer(mtl_shaders.Image);
|
||||||
var buf = try Buffer.initFill(self.device, &.{.{
|
var buf = try Buffer.initFill(self.gpu_state.device, &.{.{
|
||||||
.grid_pos = .{
|
.grid_pos = .{
|
||||||
@as(f32, @floatFromInt(p.x)),
|
@as(f32, @floatFromInt(p.x)),
|
||||||
@as(f32, @floatFromInt(p.y)),
|
@as(f32, @floatFromInt(p.y)),
|
||||||
@ -1208,7 +1206,7 @@ fn drawImagePlacement(
|
|||||||
@intFromEnum(mtl.MTLPrimitiveType.triangle),
|
@intFromEnum(mtl.MTLPrimitiveType.triangle),
|
||||||
@as(c_ulong, 6),
|
@as(c_ulong, 6),
|
||||||
@intFromEnum(mtl.MTLIndexType.uint16),
|
@intFromEnum(mtl.MTLIndexType.uint16),
|
||||||
self.buf_instance.buffer.value,
|
self.gpu_state.instance.buffer.value,
|
||||||
@as(c_ulong, 0),
|
@as(c_ulong, 0),
|
||||||
@as(c_ulong, 1),
|
@as(c_ulong, 1),
|
||||||
},
|
},
|
||||||
@ -1271,7 +1269,7 @@ fn drawCells(
|
|||||||
@intFromEnum(mtl.MTLPrimitiveType.triangle),
|
@intFromEnum(mtl.MTLPrimitiveType.triangle),
|
||||||
@as(c_ulong, 6),
|
@as(c_ulong, 6),
|
||||||
@intFromEnum(mtl.MTLIndexType.uint16),
|
@intFromEnum(mtl.MTLIndexType.uint16),
|
||||||
self.buf_instance.buffer.value,
|
self.gpu_state.instance.buffer.value,
|
||||||
@as(c_ulong, 0),
|
@as(c_ulong, 0),
|
||||||
@as(c_ulong, len),
|
@as(c_ulong, len),
|
||||||
},
|
},
|
||||||
@ -1573,7 +1571,7 @@ pub fn setScreenSize(
|
|||||||
|
|
||||||
// If we fail to create the texture, then we just don't have a screen
|
// If we fail to create the texture, then we just don't have a screen
|
||||||
// texture and our custom shaders won't run.
|
// texture and our custom shaders won't run.
|
||||||
const id = self.device.msgSend(
|
const id = self.gpu_state.device.msgSend(
|
||||||
?*anyopaque,
|
?*anyopaque,
|
||||||
objc.sel("newTextureWithDescriptor:"),
|
objc.sel("newTextureWithDescriptor:"),
|
||||||
.{desc},
|
.{desc},
|
||||||
|
Reference in New Issue
Block a user