Try making frame flipping more robust
This commit is contained in:
+84
-61
@@ -43,11 +43,13 @@ const WaylandState = struct {
|
||||
running: bool,
|
||||
configured: bool,
|
||||
|
||||
display: ?*c.wl_display,
|
||||
compositor: ?*c.wl_compositor,
|
||||
seat: ?*c.wl_seat,
|
||||
shared_memory: ?*c.wl_shm,
|
||||
xdg_wm_base: ?*c.xdg_wm_base,
|
||||
surface: ?*c.wl_surface,
|
||||
buffer: ?*c.wl_buffer,
|
||||
|
||||
xkb_context: ?*c.xkb_context,
|
||||
xkb_keymap: ?*c.xkb_keymap,
|
||||
@@ -56,7 +58,7 @@ const WaylandState = struct {
|
||||
allocator: std.mem.Allocator,
|
||||
|
||||
resize: bool,
|
||||
frame_ready: bool,
|
||||
frame_commited: bool,
|
||||
|
||||
window_resized: bool,
|
||||
window_width: i32,
|
||||
@@ -120,8 +122,10 @@ fn wlFrameHandleDone(data: ?*anyopaque, callback: ?*c.wl_callback, callback_data
|
||||
const new_callback: ?*c.wl_callback = c.wl_surface_frame(wl_state.surface);
|
||||
_ = c.wl_callback_add_listener(new_callback, &frame_callback_listener, wl_state);
|
||||
|
||||
// std.debug.print("[Wayland] Frame ready\n", .{});
|
||||
wl_state.frame_ready = true;
|
||||
std.debug.print("[Wayland] Frame ready\n", .{});
|
||||
|
||||
wl_state.frame_commited = true;
|
||||
|
||||
}
|
||||
|
||||
const frame_callback_listener: c.wl_callback_listener = .{
|
||||
@@ -811,6 +815,39 @@ const registry_listener: c.wl_registry_listener = .{
|
||||
.global_remove = registryHandleGlobalRemove,
|
||||
};
|
||||
|
||||
fn pollEvents(wl_state: *WaylandState, fds: *[1]linux.pollfd) void {
|
||||
while (true) {
|
||||
const cont = std.posix.poll(fds, 0) catch |err| {
|
||||
switch (err) {
|
||||
error.Unexpected => {
|
||||
std.debug.print("Poll error: Unexpected.\n", .{});
|
||||
},
|
||||
error.SystemResources => {
|
||||
std.debug.print("Poll error: SystemResources: Kernel has no space for table allocations.\n", .{});
|
||||
},
|
||||
else => {
|
||||
std.debug.print("Poll error: network stuff idk.\n", .{});
|
||||
},
|
||||
}
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
if (cont == 0) break;
|
||||
|
||||
for (fds) |fd| {
|
||||
if (fd.revents & std.posix.POLL.IN > 0) {
|
||||
const ret = c.wl_display_dispatch(wl_state.display);
|
||||
if (ret < 0) {
|
||||
std.debug.print("Dispatch error {d}.\n", .{ret});
|
||||
wl_state.running = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() u8 {
|
||||
const display = c.wl_display_connect(null);
|
||||
if (display == null) {
|
||||
@@ -823,6 +860,7 @@ pub fn main() u8 {
|
||||
std.debug.print("[Wayland] Connection established.\n", .{});
|
||||
|
||||
var wl_state: WaylandState = undefined;
|
||||
wl_state.display = display;
|
||||
wl_state.xkb_context = null;
|
||||
wl_state.xkb_state = null;
|
||||
wl_state.xkb_keymap = null;
|
||||
@@ -884,7 +922,6 @@ pub fn main() u8 {
|
||||
|
||||
var shared_memory_pool: ?*c.wl_shm_pool = undefined;
|
||||
var shared_memory_pool_data: []u8 = undefined;
|
||||
var wl_buffer: *c.wl_buffer = undefined;
|
||||
|
||||
const monitor_update_hz: f64 = 60;
|
||||
const game_update_hz: f64 = monitor_update_hz;
|
||||
@@ -913,14 +950,15 @@ pub fn main() u8 {
|
||||
const ret: c_int = c.wl_callback_add_listener(cb, &frame_callback_listener, &wl_state);
|
||||
std.debug.print("[Wayland] Added frame callback with ret {d}.\n", .{ret});
|
||||
}
|
||||
wl_state.frame_ready = true;
|
||||
|
||||
var timer = std.time.Timer.start() catch {
|
||||
std.debug.print("[Wayland] ERROR: timer not supported.\n", .{});
|
||||
return 1;
|
||||
};
|
||||
|
||||
var fds: [1]std.os.linux.pollfd = .{
|
||||
var frame_count: u32 = 0;
|
||||
|
||||
var fds: [1]linux.pollfd = .{
|
||||
.{
|
||||
.fd = wl_fd,
|
||||
.events = std.posix.POLL.IN,
|
||||
@@ -928,36 +966,7 @@ pub fn main() u8 {
|
||||
},
|
||||
};
|
||||
while (wl_state.running) {
|
||||
outer: while (true) {
|
||||
const cont = std.posix.poll(&fds, 0) catch |err| {
|
||||
switch (err) {
|
||||
error.Unexpected => {
|
||||
std.debug.print("Poll error: Unexpected.\n", .{});
|
||||
},
|
||||
error.SystemResources => {
|
||||
std.debug.print("Poll error: SystemResources: Kernel has no space for table allocations.\n", .{});
|
||||
},
|
||||
else => {
|
||||
std.debug.print("Poll error: network stuff idk.\n", .{});
|
||||
},
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
if (cont == 0) break;
|
||||
|
||||
for (fds) |fd| {
|
||||
if (fd.revents & std.posix.POLL.IN > 0) {
|
||||
const ret = c.wl_display_dispatch(display);
|
||||
if (ret < 0) {
|
||||
std.debug.print("Dispatch error {d}.\n", .{ret});
|
||||
wl_state.running = false;
|
||||
break :outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pollEvents(&wl_state, &fds);
|
||||
|
||||
if (wl_state.resize) {
|
||||
const new_pool = createSharedMemoryPool(wl_state) catch {
|
||||
@@ -983,8 +992,8 @@ pub fn main() u8 {
|
||||
stride,
|
||||
c.WL_SHM_FORMAT_ARGB8888,
|
||||
);
|
||||
if (buffer != null) {
|
||||
wl_buffer = buffer.?;
|
||||
if (buffer) |buf| {
|
||||
wl_state.buffer = buf;
|
||||
} else {
|
||||
std.debug.print("[Wayland] Error creating buffer!\n", .{});
|
||||
wl_state.running = false;
|
||||
@@ -993,53 +1002,67 @@ pub fn main() u8 {
|
||||
|
||||
wl_state.resize = false;
|
||||
wl_state.window_resized = false;
|
||||
wl_state.frame_commited = true;
|
||||
c.wl_surface_attach(wl_state.surface, wl_state.buffer, 0, 0);
|
||||
c.wl_surface_damage_buffer(wl_state.surface, 0, 0, wl_state.window_width, wl_state.window_height);
|
||||
c.wl_surface_commit(wl_state.surface);
|
||||
}
|
||||
}
|
||||
|
||||
const render_start_time: u64 = timer.read();
|
||||
|
||||
if (wl_state.frame_ready) {
|
||||
wl_state.app_input.delta_time = frame_target_time_s;
|
||||
wl_state.app_input.delta_time = frame_target_time_s;
|
||||
|
||||
const app_offscreen_buffer: puzzle.platform.OffscreenBuffer = .{
|
||||
.width = wl_state.window_width,
|
||||
.height = wl_state.window_height,
|
||||
.stride = wl_state.window_width * 4,
|
||||
.data = shared_memory_pool_data,
|
||||
};
|
||||
puzzle.updateAndRender(&app_memory, app_offscreen_buffer, &wl_state.app_input);
|
||||
}
|
||||
const app_offscreen_buffer: puzzle.platform.OffscreenBuffer = .{
|
||||
.width = wl_state.window_width,
|
||||
.height = wl_state.window_height,
|
||||
.stride = wl_state.window_width * 4,
|
||||
.data = shared_memory_pool_data,
|
||||
};
|
||||
wl_state.app_input.controls = puzzle.platform.Controls{ .key = old_key };
|
||||
puzzle.updateAndRender(&app_memory, app_offscreen_buffer, &wl_state.app_input);
|
||||
|
||||
const render_end_time: u64 = timer.read();
|
||||
const render_time = render_end_time - render_start_time;
|
||||
const render_time_ms: f64 = @as(f64, @floatFromInt(render_time)) / @as(f64, @floatFromInt(std.time.ns_per_ms));
|
||||
|
||||
std.debug.print("[Wayland] Render: {d:2.3}ms.\n", .{ render_time_ms });
|
||||
|
||||
var sleep_time: u64 = frame_target_time_ns;
|
||||
if (render_time < frame_target_time_ns) {
|
||||
sleep_time -= render_time;
|
||||
const sleep_time_ms: f64 = @as(f64, @floatFromInt(sleep_time)) / @as(f64, @floatFromInt(std.time.ns_per_ms));
|
||||
std.debug.print("[Wayland] Sleeping: {d:2.3}ms.\n", .{ sleep_time_ms });
|
||||
std.posix.nanosleep(0, sleep_time);
|
||||
} else {
|
||||
sleep_time = 0;
|
||||
std.debug.print("MISSED FRAME\n", .{});
|
||||
std.debug.print("[Wayland] MISSED FRAME\n", .{});
|
||||
}
|
||||
|
||||
if (wl_state.frame_ready) {
|
||||
c.wl_surface_attach(wl_surface, wl_buffer, 0, 0);
|
||||
c.wl_surface_damage_buffer(wl_surface, 0, 0, wl_state.window_width, wl_state.window_height);
|
||||
c.wl_surface_commit(wl_surface);
|
||||
wl_state.frame_ready = false;
|
||||
}
|
||||
c.wl_surface_attach(wl_state.surface, wl_state.buffer, 0, 0);
|
||||
c.wl_surface_damage_buffer(wl_state.surface, 0, 0, wl_state.window_width, wl_state.window_height);
|
||||
c.wl_surface_commit(wl_state.surface);
|
||||
|
||||
_ = c.wl_display_roundtrip(display);
|
||||
var wait_frame: u32 = 0;
|
||||
while (!wl_state.frame_commited) {
|
||||
_ = c.wl_display_dispatch(display);
|
||||
wait_frame += 1;
|
||||
}
|
||||
std.debug.print("[Wayland] Waited for {d} frame(s).\n", .{wait_frame});
|
||||
|
||||
wl_state.frame_commited = false;
|
||||
|
||||
// std.posix.nanosleep(0, std.time.ns_per_ms * 32);
|
||||
|
||||
const current = timer.lap();
|
||||
const current_ms: f64 = @as(f64, @floatFromInt(current)) / std.time.ns_per_ms;
|
||||
const sleep_time_ms: f64 = @as(f64, @floatFromInt(sleep_time)) / @as(f64, @floatFromInt(std.time.ns_per_ms));
|
||||
std.debug.print(
|
||||
"Render: {d:2.3}ms, Sleeping: {d:2.3}ms, Frame: {d:.3}ms.\n",
|
||||
.{ render_time_ms, sleep_time_ms, current_ms },
|
||||
);
|
||||
// std.debug.print(
|
||||
// "[Wayland] Render: {d:2.3}ms, Sleeping: {d:2.3}ms, Frame: {d:.3}ms.\n",
|
||||
// .{ render_time_ms, sleep_time_ms, current_ms },
|
||||
// );
|
||||
std.debug.print("[Wayland] Frame done: {d:.3}ms.\n", .{ current_ms });
|
||||
|
||||
frame_count += 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
+1
-2
@@ -821,6 +821,7 @@ pub fn updateAndRender(memory: *platform.AppMemory, buffer: platform.OffscreenBu
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Animate bricks to new position
|
||||
if (clear_pressed) {
|
||||
if (valid_pos) {
|
||||
const board = state.board;
|
||||
@@ -1024,9 +1025,7 @@ pub fn updateAndRender(memory: *platform.AppMemory, buffer: platform.OffscreenBu
|
||||
const height = buffer.height - state.font.glyph_height;
|
||||
|
||||
drawString(buffer, state.font, V2.initI32(8, height - 2 * state.font.glyph_height + 8), scale, "Clear: q");
|
||||
|
||||
drawString(buffer, state.font, V2.initI32(8, height - state.font.glyph_height), scale, "Flip: w");
|
||||
|
||||
drawString(buffer, state.font, V2.initI32(8, height - 8), scale, "Rotate: e");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user