mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-21 19:26:09 +03:00
renderer/metal: implement triple-buffering
This commit is contained in:
@ -122,11 +122,6 @@ custom_shader_state: ?CustomShaderState = null,
|
|||||||
/// this will have to be part of the frame state.
|
/// this will have to be part of the frame state.
|
||||||
health: std.atomic.Value(Health) = .{ .raw = .healthy },
|
health: std.atomic.Value(Health) = .{ .raw = .healthy },
|
||||||
|
|
||||||
/// Sempahore blocking our in-flight buffer updates. For now this is just
|
|
||||||
/// one but in the future if we implement double/triple-buffering this
|
|
||||||
/// will be incremented.
|
|
||||||
inflight: std.Thread.Semaphore = .{ .permits = 1 },
|
|
||||||
|
|
||||||
/// Our GPU state
|
/// Our GPU state
|
||||||
gpu_state: GPUState,
|
gpu_state: GPUState,
|
||||||
|
|
||||||
@ -167,6 +162,21 @@ pub const GPUState = struct {
|
|||||||
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the next frame state to draw to. This will wait on the
|
||||||
|
/// semaphore to ensure that the frame is available. This must
|
||||||
|
/// always be paired with a call to releaseFrame.
|
||||||
|
pub fn nextFrame(self: *GPUState) *FrameState {
|
||||||
|
self.frame_sema.wait();
|
||||||
|
errdefer self.frame_sema.post();
|
||||||
|
self.frame_index = (self.frame_index + 1) % BufferCount;
|
||||||
|
return &self.frames[self.frame_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This should be called when the frame has completed drawing.
|
||||||
|
pub fn releaseFrame(self: *GPUState) void {
|
||||||
|
self.frame_sema.post();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// State we need duplicated for every frame. Any state that could be
|
/// State we need duplicated for every frame. Any state that could be
|
||||||
@ -566,13 +576,6 @@ pub fn init(alloc: Allocator, options: renderer.Options) !Metal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Metal) void {
|
pub fn deinit(self: *Metal) void {
|
||||||
// If we have inflight buffers, wait for completion. This ensures that
|
|
||||||
// any pending GPU operations are completed before we start deallocating
|
|
||||||
// everything. This is important because our completion callbacks access
|
|
||||||
// "self"
|
|
||||||
self.inflight.wait();
|
|
||||||
|
|
||||||
// All inflight frames are done, deinit our GPU state.
|
|
||||||
self.gpu_state.deinit();
|
self.gpu_state.deinit();
|
||||||
|
|
||||||
self.cells.deinit(self.alloc);
|
self.cells.deinit(self.alloc);
|
||||||
@ -812,12 +815,12 @@ pub fn updateFrame(
|
|||||||
pub fn drawFrame(self: *Metal, surface: *apprt.Surface) !void {
|
pub fn drawFrame(self: *Metal, surface: *apprt.Surface) !void {
|
||||||
_ = surface;
|
_ = surface;
|
||||||
|
|
||||||
// Wait for a buffer to be available.
|
// Wait for a frame to be available.
|
||||||
self.inflight.wait();
|
const frame = self.gpu_state.nextFrame();
|
||||||
errdefer self.inflight.post();
|
errdefer self.gpu_state.releaseFrame();
|
||||||
|
//log.debug("drawing frame index={}", .{self.gpu_state.frame_index});
|
||||||
|
|
||||||
// Setup our frame data
|
// Setup our frame data
|
||||||
const frame = &self.gpu_state.frames[self.gpu_state.frame_index];
|
|
||||||
try frame.uniforms.sync(self.gpu_state.device, &.{self.uniforms});
|
try frame.uniforms.sync(self.gpu_state.device, &.{self.uniforms});
|
||||||
try frame.cells_bg.sync(self.gpu_state.device, self.cells_bg.items);
|
try frame.cells_bg.sync(self.gpu_state.device, self.cells_bg.items);
|
||||||
try frame.cells.sync(self.gpu_state.device, self.cells.items);
|
try frame.cells.sync(self.gpu_state.device, self.cells.items);
|
||||||
@ -1036,7 +1039,7 @@ fn bufferCompleted(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Always release our semaphore
|
// Always release our semaphore
|
||||||
self.inflight.post();
|
self.gpu_state.releaseFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn drawPostShader(
|
fn drawPostShader(
|
||||||
|
Reference in New Issue
Block a user