mach: correct vsync mode setting

This correctly sets presentation modes for vsync, both at startup and at runtime via
a `setOptions` request.

Note: There may still be platforms where setting vsync is not enough, and a frame rate
limiter is needed to achieve proper synchronization. This is tracked in hexops/mach#444
and not fixed by this change.

Fixes hexops/mach#307

Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
Stephen Gutekanst 2022-08-18 10:33:32 -07:00
parent edc3b5d60e
commit eb0eceb707
3 changed files with 19 additions and 11 deletions

View file

@ -34,15 +34,11 @@ target_desc: gpu.SwapChain.Descriptor,
internal: platform.Type, internal: platform.Type,
pub fn init(allocator: std.mem.Allocator) !Core { pub fn init(allocator: std.mem.Allocator, core: *Core) !void {
var core: Core = undefined;
core.allocator = allocator; core.allocator = allocator;
core.options = structs.Options{}; core.options = structs.Options{};
core.timer = try Timer.start(); core.timer = try Timer.start();
core.internal = try platform.Type.init(allocator, core);
core.internal = try platform.Type.init(allocator, &core);
return core;
} }
/// Set runtime options for application, like title, window size etc. /// Set runtime options for application, like title, window size etc.

View file

@ -19,6 +19,7 @@ pub const log_level = if (@hasDecl(App, "log_level")) App.log_level else std.log
pub const Platform = struct { pub const Platform = struct {
window: glfw.Window, window: glfw.Window,
core: *Core,
backend_type: gpu.BackendType, backend_type: gpu.BackendType,
allocator: std.mem.Allocator, allocator: std.mem.Allocator,
events: EventQueue = .{}, events: EventQueue = .{},
@ -129,7 +130,11 @@ pub const Platform = struct {
.format = core.swap_chain_format, .format = core.swap_chain_format,
.width = framebuffer_size.width, .width = framebuffer_size.width,
.height = framebuffer_size.height, .height = framebuffer_size.height,
.present_mode = .fifo, .present_mode = switch (options.vsync) {
.none => .immediate,
.double => .fifo,
.triple => .mailbox,
},
}; };
device.?.setUncapturedErrorCallback({}, util.printUnhandledErrorCallback); device.?.setUncapturedErrorCallback({}, util.printUnhandledErrorCallback);
@ -144,6 +149,7 @@ pub const Platform = struct {
return Platform{ return Platform{
.window = window, .window = window,
.core = core,
.backend_type = backend_type, .backend_type = backend_type,
.allocator = core.allocator, .allocator = core.allocator,
.last_window_size = .{ .width = window_size.width, .height = window_size.height }, .last_window_size = .{ .width = window_size.width, .height = window_size.height },
@ -338,6 +344,11 @@ pub const Platform = struct {
@bitCast(glfw.Window.SizeOptional, options.size_min), @bitCast(glfw.Window.SizeOptional, options.size_min),
@bitCast(glfw.Window.SizeOptional, options.size_max), @bitCast(glfw.Window.SizeOptional, options.size_max),
); );
platform.core.target_desc.present_mode = switch (options.vsync) {
.none => .immediate,
.double => .fifo,
.triple => .mailbox,
};
if (options.fullscreen) { if (options.fullscreen) {
platform.last_position = try platform.window.getPos(); platform.last_position = try platform.window.getPos();
@ -406,8 +417,9 @@ pub const Platform = struct {
pub fn pollEvent(platform: *Platform) ?structs.Event { pub fn pollEvent(platform: *Platform) ?structs.Event {
if (platform.events.popFirst()) |n| { if (platform.events.popFirst()) |n| {
defer platform.allocator.destroy(n); const data = n.data;
return n.data; platform.allocator.destroy(n);
return data;
} }
return null; return null;
} }
@ -607,7 +619,7 @@ pub fn main() !void {
pub fn coreInit(allocator: std.mem.Allocator) !*Core { pub fn coreInit(allocator: std.mem.Allocator) !*Core {
const core: *Core = try allocator.create(Core); const core: *Core = try allocator.create(Core);
errdefer allocator.destroy(core); errdefer allocator.destroy(core);
core.* = try Core.init(allocator); try Core.init(allocator, core);
// Glfw specific: initialize the user pointer used in callbacks // Glfw specific: initialize the user pointer used in callbacks
core.*.internal.initCallback(); core.*.internal.initCallback();

View file

@ -286,7 +286,7 @@ export fn wasmInit() void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){}; var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator(); const allocator = gpa.allocator();
core = Core.init(allocator) catch unreachable; Core.init(allocator, &core) catch unreachable;
app.init(&core) catch {}; app.init(&core) catch {};
} }