mach: add a standard way to access platform specific structs

This is done by adding platform.zig which is a file providing types like
``CoreType``, ``GpuDriverType`` and ``BackingTimerType``.
This commit is contained in:
iddev5 2022-05-23 13:23:26 +05:30 committed by Stephen Gutekanst
parent e5050e856e
commit f3e2b8b74c
5 changed files with 74 additions and 77 deletions

View file

@ -3,6 +3,7 @@ const Allocator = std.mem.Allocator;
const builtin = @import("builtin"); const builtin = @import("builtin");
const glfw = @import("glfw"); const glfw = @import("glfw");
const gpu = @import("gpu"); const gpu = @import("gpu");
const platform = @import("platform.zig");
const structs = @import("structs.zig"); const structs = @import("structs.zig");
const enums = @import("enums.zig"); const enums = @import("enums.zig");
const Timer = @import("Timer.zig"); const Timer = @import("Timer.zig");
@ -29,7 +30,7 @@ delta_time_ns: u64 = 0,
timer: Timer, timer: Timer,
pub const Core = struct { pub const Core = struct {
internal: GetCoreInternalType(), internal: platform.CoreType,
pub fn setShouldClose(core: *Core, value: bool) void { pub fn setShouldClose(core: *Core, value: bool) void {
core.internal.setShouldClose(value); core.internal.setShouldClose(value);
@ -59,7 +60,7 @@ pub const Core = struct {
}; };
pub const GpuDriver = struct { pub const GpuDriver = struct {
internal: GetGpuDriverInternalType(), internal: platform.GpuDriverType,
device: gpu.Device, device: gpu.Device,
backend_type: gpu.Adapter.BackendType, backend_type: gpu.Adapter.BackendType,
@ -82,18 +83,8 @@ pub fn init(allocator: std.mem.Allocator, options: structs.Options) !Engine {
// Note: if in future, there is a conflict in init() signature of different backends, // Note: if in future, there is a conflict in init() signature of different backends,
// move these calls to the entry point file, which is native.zig for Glfw, for example // move these calls to the entry point file, which is native.zig for Glfw, for example
engine.core.internal = try GetCoreInternalType().init(allocator, &engine); engine.core.internal = try platform.CoreType.init(allocator, &engine);
engine.gpu_driver.internal = try GetGpuDriverInternalType().init(allocator, &engine); engine.gpu_driver.internal = try platform.GpuDriverType.init(allocator, &engine);
return engine; return engine;
} }
fn GetCoreInternalType() type {
if (builtin.cpu.arch == .wasm32) return @import("wasm.zig").CoreWasm;
return @import("native.zig").CoreGlfw;
}
fn GetGpuDriverInternalType() type {
if (builtin.cpu.arch == .wasm32) return @import("wasm.zig").GpuDriverWeb;
return @import("native.zig").GpuDriverNative;
}

View file

@ -1,48 +1,14 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const platform = @import("platform.zig");
const Timer = @This(); const Timer = @This();
backing_timer: BackingTimerType = undefined, backing_timer: platform.BackingTimerType = undefined,
// TODO: verify declarations and its signatures
const BackingTimerType = if (builtin.cpu.arch == .wasm32) struct {
initial: f64 = undefined,
const js = struct {
extern fn machPerfNow() f64;
};
const WasmTimer = @This();
fn start() !WasmTimer {
return WasmTimer{ .initial = js.machPerfNow() };
}
fn read(timer: *WasmTimer) u64 {
return timeToNs(js.machPerfNow() - timer.initial);
}
fn reset(timer: *WasmTimer) void {
timer.initial = js.machPerfNow();
}
fn lap(timer: *WasmTimer) u64 {
const now = js.machPerfNow();
const initial = timer.initial;
timer.initial = now;
return timeToNs(now - initial);
}
fn timeToNs(t: f64) u64 {
return @floatToInt(u64, t) * 1000000;
}
} else std.time.Timer;
/// Initialize the timer. /// Initialize the timer.
pub fn start() !Timer { pub fn start() !Timer {
return Timer{ return Timer{
.backing_timer = try BackingTimerType.start(), .backing_timer = try platform.BackingTimerType.start(),
}; };
} }

View file

@ -8,7 +8,7 @@ const enums = @import("enums.zig");
const util = @import("util.zig"); const util = @import("util.zig");
const c = @import("c.zig").c; const c = @import("c.zig").c;
pub const CoreGlfw = struct { pub const Core = struct {
window: glfw.Window, window: glfw.Window,
backend_type: gpu.Adapter.BackendType, backend_type: gpu.Adapter.BackendType,
allocator: std.mem.Allocator, allocator: std.mem.Allocator,
@ -19,14 +19,14 @@ pub const CoreGlfw = struct {
const EventNode = EventQueue.Node; const EventNode = EventQueue.Node;
const UserPtr = struct { const UserPtr = struct {
core: *CoreGlfw, core: *Core,
}; };
pub fn init(allocator: std.mem.Allocator, engine: *Engine) !CoreGlfw { pub fn init(allocator: std.mem.Allocator, engine: *Engine) !Core {
const options = engine.options; const options = engine.options;
const backend_type = try util.detectBackendType(allocator); const backend_type = try util.detectBackendType(allocator);
glfw.setErrorCallback(CoreGlfw.errorCallback); glfw.setErrorCallback(Core.errorCallback);
try glfw.init(.{}); try glfw.init(.{});
// Create the test window and discover adapters using it (esp. for OpenGL) // Create the test window and discover adapters using it (esp. for OpenGL)
@ -41,20 +41,20 @@ pub const CoreGlfw = struct {
hints, hints,
); );
return CoreGlfw{ return Core{
.window = window, .window = window,
.backend_type = backend_type, .backend_type = backend_type,
.allocator = engine.allocator, .allocator = engine.allocator,
}; };
} }
fn pushEvent(self: *CoreGlfw, event: structs.Event) void { fn pushEvent(self: *Core, event: structs.Event) void {
const node = self.allocator.create(EventNode) catch unreachable; const node = self.allocator.create(EventNode) catch unreachable;
node.* = .{ .data = event }; node.* = .{ .data = event };
self.events.append(node); self.events.append(node);
} }
fn initCallback(self: *CoreGlfw) void { fn initCallback(self: *Core) void {
self.user_ptr = UserPtr{ .core = self }; self.user_ptr = UserPtr{ .core = self };
self.window.setUserPointer(&self.user_ptr); self.window.setUserPointer(&self.user_ptr);
@ -84,28 +84,28 @@ pub const CoreGlfw = struct {
self.window.setKeyCallback(callback); self.window.setKeyCallback(callback);
} }
pub fn setShouldClose(self: *CoreGlfw, value: bool) void { pub fn setShouldClose(self: *Core, value: bool) void {
self.window.setShouldClose(value); self.window.setShouldClose(value);
} }
pub fn getFramebufferSize(self: *CoreGlfw) !structs.Size { pub fn getFramebufferSize(self: *Core) !structs.Size {
const size = try self.window.getFramebufferSize(); const size = try self.window.getFramebufferSize();
return @bitCast(structs.Size, size); return @bitCast(structs.Size, size);
} }
pub fn getWindowSize(self: *CoreGlfw) !structs.Size { pub fn getWindowSize(self: *Core) !structs.Size {
const size = try self.window.getSize(); const size = try self.window.getSize();
return @bitCast(structs.Size, size); return @bitCast(structs.Size, size);
} }
pub fn setSizeLimits(self: *CoreGlfw, min: structs.SizeOptional, max: structs.SizeOptional) !void { pub fn setSizeLimits(self: *Core, min: structs.SizeOptional, max: structs.SizeOptional) !void {
try self.window.setSizeLimits( try self.window.setSizeLimits(
@bitCast(glfw.Window.SizeOptional, min), @bitCast(glfw.Window.SizeOptional, min),
@bitCast(glfw.Window.SizeOptional, max), @bitCast(glfw.Window.SizeOptional, max),
); );
} }
pub fn pollEvent(self: *CoreGlfw) ?structs.Event { pub fn pollEvent(self: *Core) ?structs.Event {
if (self.events.popFirst()) |n| { if (self.events.popFirst()) |n| {
defer self.allocator.destroy(n); defer self.allocator.destroy(n);
return n.data; return n.data;
@ -250,10 +250,10 @@ pub const CoreGlfw = struct {
} }
}; };
pub const GpuDriverNative = struct { pub const GpuDriver = struct {
native_instance: gpu.NativeInstance, native_instance: gpu.NativeInstance,
pub fn init(_: std.mem.Allocator, engine: *Engine) !GpuDriverNative { pub fn init(_: std.mem.Allocator, engine: *Engine) !GpuDriver {
const options = engine.options; const options = engine.options;
const window = engine.core.internal.window; const window = engine.core.internal.window;
const backend_type = engine.core.internal.backend_type; const backend_type = engine.core.internal.backend_type;
@ -382,12 +382,14 @@ pub const GpuDriverNative = struct {
engine.gpu_driver.current_desc = descriptor; engine.gpu_driver.current_desc = descriptor;
engine.gpu_driver.target_desc = descriptor; engine.gpu_driver.target_desc = descriptor;
return GpuDriverNative{ return GpuDriver{
.native_instance = native_instance, .native_instance = native_instance,
}; };
} }
}; };
pub const BackingTimer = std.time.Timer;
// TODO: check signatures // TODO: check signatures
comptime { comptime {
if (!@hasDecl(App, "init")) @compileError("App must export 'pub fn init(app: *App, engine: *mach.Engine) !void'"); if (!@hasDecl(App, "init")) @compileError("App must export 'pub fn init(app: *App, engine: *mach.Engine) !void'");

8
src/platform.zig Normal file
View file

@ -0,0 +1,8 @@
const builtin = @import("builtin");
const Platform = if (builtin.cpu.arch == .wasm32) @import("wasm.zig") else @import("native.zig");
// TODO: verify declarations and its signatures
pub const CoreType = Platform.Core;
pub const GpuDriverType = Platform.GpuDriver;
pub const BackingTimerType = Platform.BackingTimer;

View file

@ -12,6 +12,7 @@ const js = struct {
extern fn machCanvasGetWidth(canvas: CanvasId) u32; extern fn machCanvasGetWidth(canvas: CanvasId) u32;
extern fn machCanvasGetHeight(canvas: CanvasId) u32; extern fn machCanvasGetHeight(canvas: CanvasId) u32;
extern fn machPerfNow() f64;
extern fn machLog(str: [*]const u8, len: u32) void; extern fn machLog(str: [*]const u8, len: u32) void;
extern fn machLogWrite(str: [*]const u8, len: u32) void; extern fn machLogWrite(str: [*]const u8, len: u32) void;
extern fn machLogFlush() void; extern fn machLogFlush() void;
@ -20,11 +21,11 @@ const js = struct {
pub const CanvasId = u32; pub const CanvasId = u32;
pub const CoreWasm = struct { pub const Core = struct {
id: CanvasId, id: CanvasId,
selector_id: []const u8, selector_id: []const u8,
pub fn init(allocator: std.mem.Allocator, eng: *Engine) !CoreWasm { pub fn init(allocator: std.mem.Allocator, eng: *Engine) !Core {
const options = eng.options; const options = eng.options;
var selector = [1]u8{0} ** 15; var selector = [1]u8{0} ** 15;
const id = js.machCanvasInit(options.width, options.height, &selector[0]); const id = js.machCanvasInit(options.width, options.height, &selector[0]);
@ -32,35 +33,64 @@ pub const CoreWasm = struct {
const title = std.mem.span(options.title); const title = std.mem.span(options.title);
js.machCanvasSetTitle(id, title.ptr, title.len); js.machCanvasSetTitle(id, title.ptr, title.len);
return CoreWasm{ return Core{
.id = id, .id = id,
.selector_id = try allocator.dupe(u8, selector[0 .. selector.len - @as(u32, if (selector[selector.len - 1] == 0) 1 else 0)]), .selector_id = try allocator.dupe(u8, selector[0 .. selector.len - @as(u32, if (selector[selector.len - 1] == 0) 1 else 0)]),
}; };
} }
pub fn setShouldClose(_: *CoreWasm, _: bool) void {} pub fn setShouldClose(_: *Core, _: bool) void {}
pub fn getFramebufferSize(_: *CoreWasm) !structs.Size { pub fn getFramebufferSize(_: *Core) !structs.Size {
return structs.Size{ .width = 0, .height = 0 }; return structs.Size{ .width = 0, .height = 0 };
} }
pub fn getWindowSize(core: *CoreWasm) !structs.Size { pub fn getWindowSize(core: *Core) !structs.Size {
return structs.Size{ return structs.Size{
.width = js.machCanvasGetWidth(core.id), .width = js.machCanvasGetWidth(core.id),
.height = js.machCanvasGetHeight(core.id), .height = js.machCanvasGetHeight(core.id),
}; };
} }
pub fn setSizeLimits(_: *CoreWasm, _: structs.SizeOptional, _: structs.SizeOptional) !void {} pub fn setSizeLimits(_: *Core, _: structs.SizeOptional, _: structs.SizeOptional) !void {}
pub fn pollEvent(_: *CoreWasm) ?structs.Event { pub fn pollEvent(_: *Core) ?structs.Event {
return null; return null;
} }
}; };
pub const GpuDriverWeb = struct { pub const GpuDriver = struct {
pub fn init(_: std.mem.Allocator, _: *Engine) !GpuDriverWeb { pub fn init(_: std.mem.Allocator, _: *Engine) !GpuDriver {
return GpuDriverWeb{}; return GpuDriver{};
}
};
pub const BackingTimer = struct {
initial: f64 = undefined,
const WasmTimer = @This();
pub fn start() !WasmTimer {
return WasmTimer{ .initial = js.machPerfNow() };
}
pub fn read(timer: *WasmTimer) u64 {
return timeToNs(js.machPerfNow() - timer.initial);
}
pub fn reset(timer: *WasmTimer) void {
timer.initial = js.machPerfNow();
}
pub fn lap(timer: *WasmTimer) u64 {
const now = js.machPerfNow();
const initial = timer.initial;
timer.initial = now;
return timeToNs(now - initial);
}
fn timeToNs(t: f64) u64 {
return @floatToInt(u64, t) * 1000000;
} }
}; };