Try making frame flipping more robust
This commit is contained in:
+84
-61
@@ -43,11 +43,13 @@ const WaylandState = struct {
|
|||||||
running: bool,
|
running: bool,
|
||||||
configured: bool,
|
configured: bool,
|
||||||
|
|
||||||
|
display: ?*c.wl_display,
|
||||||
compositor: ?*c.wl_compositor,
|
compositor: ?*c.wl_compositor,
|
||||||
seat: ?*c.wl_seat,
|
seat: ?*c.wl_seat,
|
||||||
shared_memory: ?*c.wl_shm,
|
shared_memory: ?*c.wl_shm,
|
||||||
xdg_wm_base: ?*c.xdg_wm_base,
|
xdg_wm_base: ?*c.xdg_wm_base,
|
||||||
surface: ?*c.wl_surface,
|
surface: ?*c.wl_surface,
|
||||||
|
buffer: ?*c.wl_buffer,
|
||||||
|
|
||||||
xkb_context: ?*c.xkb_context,
|
xkb_context: ?*c.xkb_context,
|
||||||
xkb_keymap: ?*c.xkb_keymap,
|
xkb_keymap: ?*c.xkb_keymap,
|
||||||
@@ -56,7 +58,7 @@ const WaylandState = struct {
|
|||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
|
|
||||||
resize: bool,
|
resize: bool,
|
||||||
frame_ready: bool,
|
frame_commited: bool,
|
||||||
|
|
||||||
window_resized: bool,
|
window_resized: bool,
|
||||||
window_width: i32,
|
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);
|
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);
|
_ = c.wl_callback_add_listener(new_callback, &frame_callback_listener, wl_state);
|
||||||
|
|
||||||
// std.debug.print("[Wayland] Frame ready\n", .{});
|
std.debug.print("[Wayland] Frame ready\n", .{});
|
||||||
wl_state.frame_ready = true;
|
|
||||||
|
wl_state.frame_commited = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const frame_callback_listener: c.wl_callback_listener = .{
|
const frame_callback_listener: c.wl_callback_listener = .{
|
||||||
@@ -811,6 +815,39 @@ const registry_listener: c.wl_registry_listener = .{
|
|||||||
.global_remove = registryHandleGlobalRemove,
|
.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 {
|
pub fn main() u8 {
|
||||||
const display = c.wl_display_connect(null);
|
const display = c.wl_display_connect(null);
|
||||||
if (display == null) {
|
if (display == null) {
|
||||||
@@ -823,6 +860,7 @@ pub fn main() u8 {
|
|||||||
std.debug.print("[Wayland] Connection established.\n", .{});
|
std.debug.print("[Wayland] Connection established.\n", .{});
|
||||||
|
|
||||||
var wl_state: WaylandState = undefined;
|
var wl_state: WaylandState = undefined;
|
||||||
|
wl_state.display = display;
|
||||||
wl_state.xkb_context = null;
|
wl_state.xkb_context = null;
|
||||||
wl_state.xkb_state = null;
|
wl_state.xkb_state = null;
|
||||||
wl_state.xkb_keymap = 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: ?*c.wl_shm_pool = undefined;
|
||||||
var shared_memory_pool_data: []u8 = undefined;
|
var shared_memory_pool_data: []u8 = undefined;
|
||||||
var wl_buffer: *c.wl_buffer = undefined;
|
|
||||||
|
|
||||||
const monitor_update_hz: f64 = 60;
|
const monitor_update_hz: f64 = 60;
|
||||||
const game_update_hz: f64 = monitor_update_hz;
|
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);
|
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});
|
std.debug.print("[Wayland] Added frame callback with ret {d}.\n", .{ret});
|
||||||
}
|
}
|
||||||
wl_state.frame_ready = true;
|
|
||||||
|
|
||||||
var timer = std.time.Timer.start() catch {
|
var timer = std.time.Timer.start() catch {
|
||||||
std.debug.print("[Wayland] ERROR: timer not supported.\n", .{});
|
std.debug.print("[Wayland] ERROR: timer not supported.\n", .{});
|
||||||
return 1;
|
return 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
var fds: [1]std.os.linux.pollfd = .{
|
var frame_count: u32 = 0;
|
||||||
|
|
||||||
|
var fds: [1]linux.pollfd = .{
|
||||||
.{
|
.{
|
||||||
.fd = wl_fd,
|
.fd = wl_fd,
|
||||||
.events = std.posix.POLL.IN,
|
.events = std.posix.POLL.IN,
|
||||||
@@ -928,36 +966,7 @@ pub fn main() u8 {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
while (wl_state.running) {
|
while (wl_state.running) {
|
||||||
outer: while (true) {
|
pollEvents(&wl_state, &fds);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wl_state.resize) {
|
if (wl_state.resize) {
|
||||||
const new_pool = createSharedMemoryPool(wl_state) catch {
|
const new_pool = createSharedMemoryPool(wl_state) catch {
|
||||||
@@ -983,8 +992,8 @@ pub fn main() u8 {
|
|||||||
stride,
|
stride,
|
||||||
c.WL_SHM_FORMAT_ARGB8888,
|
c.WL_SHM_FORMAT_ARGB8888,
|
||||||
);
|
);
|
||||||
if (buffer != null) {
|
if (buffer) |buf| {
|
||||||
wl_buffer = buffer.?;
|
wl_state.buffer = buf;
|
||||||
} else {
|
} else {
|
||||||
std.debug.print("[Wayland] Error creating buffer!\n", .{});
|
std.debug.print("[Wayland] Error creating buffer!\n", .{});
|
||||||
wl_state.running = false;
|
wl_state.running = false;
|
||||||
@@ -993,53 +1002,67 @@ pub fn main() u8 {
|
|||||||
|
|
||||||
wl_state.resize = false;
|
wl_state.resize = false;
|
||||||
wl_state.window_resized = 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();
|
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 = .{
|
const app_offscreen_buffer: puzzle.platform.OffscreenBuffer = .{
|
||||||
.width = wl_state.window_width,
|
.width = wl_state.window_width,
|
||||||
.height = wl_state.window_height,
|
.height = wl_state.window_height,
|
||||||
.stride = wl_state.window_width * 4,
|
.stride = wl_state.window_width * 4,
|
||||||
.data = shared_memory_pool_data,
|
.data = shared_memory_pool_data,
|
||||||
};
|
};
|
||||||
puzzle.updateAndRender(&app_memory, app_offscreen_buffer, &wl_state.app_input);
|
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_end_time: u64 = timer.read();
|
||||||
const render_time = render_end_time - render_start_time;
|
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));
|
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;
|
var sleep_time: u64 = frame_target_time_ns;
|
||||||
if (render_time < frame_target_time_ns) {
|
if (render_time < frame_target_time_ns) {
|
||||||
sleep_time -= render_time;
|
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);
|
std.posix.nanosleep(0, sleep_time);
|
||||||
} else {
|
} else {
|
||||||
sleep_time = 0;
|
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_state.surface, wl_state.buffer, 0, 0);
|
||||||
c.wl_surface_attach(wl_surface, wl_buffer, 0, 0);
|
c.wl_surface_damage_buffer(wl_state.surface, 0, 0, wl_state.window_width, wl_state.window_height);
|
||||||
c.wl_surface_damage_buffer(wl_surface, 0, 0, wl_state.window_width, wl_state.window_height);
|
c.wl_surface_commit(wl_state.surface);
|
||||||
c.wl_surface_commit(wl_surface);
|
|
||||||
wl_state.frame_ready = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = 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);
|
// std.posix.nanosleep(0, std.time.ns_per_ms * 32);
|
||||||
|
|
||||||
const current = timer.lap();
|
const current = timer.lap();
|
||||||
const current_ms: f64 = @as(f64, @floatFromInt(current)) / std.time.ns_per_ms;
|
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(
|
||||||
std.debug.print(
|
// "[Wayland] Render: {d:2.3}ms, Sleeping: {d:2.3}ms, Frame: {d:.3}ms.\n",
|
||||||
"Render: {d:2.3}ms, Sleeping: {d:2.3}ms, Frame: {d:.3}ms.\n",
|
// .{ render_time_ms, sleep_time_ms, current_ms },
|
||||||
.{ 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;
|
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 (clear_pressed) {
|
||||||
if (valid_pos) {
|
if (valid_pos) {
|
||||||
const board = state.board;
|
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;
|
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 - 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 - state.font.glyph_height), scale, "Flip: w");
|
||||||
|
|
||||||
drawString(buffer, state.font, V2.initI32(8, height - 8), scale, "Rotate: e");
|
drawString(buffer, state.font, V2.initI32(8, height - 8), scale, "Rotate: e");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user