diff --git a/examples/core/custom-entrypoint/App.zig b/examples/core/custom-entrypoint/App.zig index 8fc250d1..49ceb950 100644 --- a/examples/core/custom-entrypoint/App.zig +++ b/examples/core/custom-entrypoint/App.zig @@ -11,7 +11,7 @@ pub const systems = .{ .tick = .{ .handler = tick }, }; -title_timer: mach.Timer, +title_timer: mach.time.Timer, pipeline: *gpu.RenderPipeline, pub fn deinit(core: *mach.Core.Mod, app: *Mod) void { @@ -62,7 +62,7 @@ fn init(app: *Mod, core: *mach.Core.Mod) !void { // Store our render pipeline in our module's state, so we can access it later on. app.init(.{ - .title_timer = try mach.Timer.start(), + .title_timer = try mach.time.Timer.start(), .pipeline = pipeline, }); try updateWindowTitle(core); diff --git a/examples/core/triangle/App.zig b/examples/core/triangle/App.zig index 8fc250d1..49ceb950 100644 --- a/examples/core/triangle/App.zig +++ b/examples/core/triangle/App.zig @@ -11,7 +11,7 @@ pub const systems = .{ .tick = .{ .handler = tick }, }; -title_timer: mach.Timer, +title_timer: mach.time.Timer, pipeline: *gpu.RenderPipeline, pub fn deinit(core: *mach.Core.Mod, app: *Mod) void { @@ -62,7 +62,7 @@ fn init(app: *Mod, core: *mach.Core.Mod) !void { // Store our render pipeline in our module's state, so we can access it later on. app.init(.{ - .title_timer = try mach.Timer.start(), + .title_timer = try mach.time.Timer.start(), .pipeline = pipeline, }); try updateWindowTitle(core); diff --git a/examples/custom-renderer/App.zig b/examples/custom-renderer/App.zig index 2ab112a5..89d47bb8 100644 --- a/examples/custom-renderer/App.zig +++ b/examples/custom-renderer/App.zig @@ -8,11 +8,11 @@ const Vec2 = math.Vec2; const Vec3 = math.Vec3; // Global state for our game module. -timer: mach.Timer, +timer: mach.time.Timer, player: mach.EntityID, direction: Vec2 = vec2(0, 0), spawning: bool = false, -spawn_timer: mach.Timer, +spawn_timer: mach.time.Timer, // Components our game module defines. pub const components = .{ @@ -82,8 +82,8 @@ fn init( // file. If this is not done, then app.state() will panic indicating the state was never // initialized. app.init(.{ - .timer = try mach.Timer.start(), - .spawn_timer = try mach.Timer.start(), + .timer = try mach.time.Timer.start(), + .spawn_timer = try mach.time.Timer.start(), .player = player, }); diff --git a/examples/glyphs/App.zig b/examples/glyphs/App.zig index 20b75bd2..b6ffbaa5 100644 --- a/examples/glyphs/App.zig +++ b/examples/glyphs/App.zig @@ -12,12 +12,12 @@ const Mat4x4 = math.Mat4x4; const Glyphs = @import("Glyphs.zig"); -timer: mach.Timer, +timer: mach.time.Timer, player: mach.EntityID, direction: Vec2 = vec2(0, 0), spawning: bool = false, -spawn_timer: mach.Timer, -fps_timer: mach.Timer, +spawn_timer: mach.time.Timer, +fps_timer: mach.time.Timer, frame_count: usize, sprites: usize, rand: std.rand.DefaultPrng, @@ -88,10 +88,10 @@ fn init( sprite.schedule(.update); app.init(.{ - .timer = try mach.Timer.start(), - .spawn_timer = try mach.Timer.start(), + .timer = try mach.time.Timer.start(), + .spawn_timer = try mach.time.Timer.start(), .player = player, - .fps_timer = try mach.Timer.start(), + .fps_timer = try mach.time.Timer.start(), .frame_count = 0, .sprites = 0, .rand = std.rand.DefaultPrng.init(1337), diff --git a/examples/hardware-check/App.zig b/examples/hardware-check/App.zig index fdca3e6d..c950aef6 100644 --- a/examples/hardware-check/App.zig +++ b/examples/hardware-check/App.zig @@ -20,10 +20,10 @@ var gpa = std.heap.GeneralPurposeAllocator(.{}){}; info_text: mach.EntityID, info_text_style: mach.EntityID, -timer: mach.Timer, +timer: mach.time.Timer, gotta_go_fast: bool = false, -spawn_timer: mach.Timer, -fps_timer: mach.Timer, +spawn_timer: mach.time.Timer, +fps_timer: mach.time.Timer, frame_count: usize, frame_rate: usize, num_sprites_spawned: usize, @@ -141,9 +141,9 @@ fn init( app.init(.{ .info_text = info_text, .info_text_style = style1, - .timer = try mach.Timer.start(), - .spawn_timer = try mach.Timer.start(), - .fps_timer = try mach.Timer.start(), + .timer = try mach.time.Timer.start(), + .spawn_timer = try mach.time.Timer.start(), + .fps_timer = try mach.time.Timer.start(), .frame_count = 0, .frame_rate = 0, .num_sprites_spawned = 0, diff --git a/examples/sprite/App.zig b/examples/sprite/App.zig index ceff50d4..fc72671d 100644 --- a/examples/sprite/App.zig +++ b/examples/sprite/App.zig @@ -17,12 +17,12 @@ const Mat4x4 = math.Mat4x4; // TODO: banish global allocator var gpa = std.heap.GeneralPurposeAllocator(.{}){}; -timer: mach.Timer, +timer: mach.time.Timer, player: mach.EntityID, direction: Vec2 = vec2(0, 0), spawning: bool = false, -spawn_timer: mach.Timer, -fps_timer: mach.Timer, +spawn_timer: mach.time.Timer, +fps_timer: mach.time.Timer, frame_count: usize, sprites: usize, rand: std.rand.DefaultPrng, @@ -92,10 +92,10 @@ fn init( sprite.schedule(.update); app.init(.{ - .timer = try mach.Timer.start(), - .spawn_timer = try mach.Timer.start(), + .timer = try mach.time.Timer.start(), + .spawn_timer = try mach.time.Timer.start(), .player = player, - .fps_timer = try mach.Timer.start(), + .fps_timer = try mach.time.Timer.start(), .frame_count = 0, .sprites = 0, .rand = std.rand.DefaultPrng.init(1337), diff --git a/examples/text/App.zig b/examples/text/App.zig index 3409f55d..cbe9e5f8 100644 --- a/examples/text/App.zig +++ b/examples/text/App.zig @@ -14,12 +14,12 @@ const Vec3 = math.Vec3; const Mat3x3 = math.Mat3x3; const Mat4x4 = math.Mat4x4; -timer: mach.Timer, +timer: mach.time.Timer, player: mach.EntityID, direction: Vec2 = vec2(0, 0), spawning: bool = false, -spawn_timer: mach.Timer, -fps_timer: mach.Timer, +spawn_timer: mach.time.Timer, +fps_timer: mach.time.Timer, frame_count: usize, rand: std.rand.DefaultPrng, time: f32, @@ -104,10 +104,10 @@ fn init( text.schedule(.update); app.init(.{ - .timer = try mach.Timer.start(), - .spawn_timer = try mach.Timer.start(), + .timer = try mach.time.Timer.start(), + .spawn_timer = try mach.time.Timer.start(), .player = player, - .fps_timer = try mach.Timer.start(), + .fps_timer = try mach.time.Timer.start(), .frame_count = 0, .rand = std.rand.DefaultPrng.init(1337), .time = 0, diff --git a/src/Core.zig b/src/Core.zig index ddfb86dc..e118e6ed 100644 --- a/src/Core.zig +++ b/src/Core.zig @@ -8,8 +8,6 @@ const log = std.log.scoped(.mach); const gamemode_log = std.log.scoped(.gamemode); pub const sysgpu = @import("../main.zig").sysgpu; -pub const Timer = @import("core/Timer.zig"); -const Frequency = @import("core/Frequency.zig"); pub const Platform = switch (build_options.core_platform) { .wasm => @panic("TODO: support mach.Core WASM platform"), @@ -135,10 +133,10 @@ state: enum { exited, } = .running, linux_gamemode: ?bool = null, -frame: Frequency, +frame: mach.time.Frequency, // Might be accessed by Platform backend -input: Frequency, +input: mach.time.Frequency, swap_chain_update: std.Thread.ResetEvent = .{}, // GPU @@ -1095,12 +1093,6 @@ comptime { assertHasDecl(Platform, "mousePressed"); assertHasDecl(Platform, "mouseReleased"); assertHasDecl(Platform, "mousePosition"); - - // Timer - assertHasDecl(@This().Timer, "start"); - assertHasDecl(@This().Timer, "read"); - assertHasDecl(@This().Timer, "reset"); - assertHasDecl(@This().Timer, "lap"); } fn assertHasDecl(comptime T: anytype, comptime decl_name: []const u8) void { @@ -1112,8 +1104,6 @@ fn assertHasField(comptime T: anytype, comptime field_name: []const u8) void { } test { - @import("std").testing.refAllDecls(Timer); - @import("std").testing.refAllDecls(Frequency); @import("std").testing.refAllDecls(Platform); @import("std").testing.refAllDeclsRecursive(InitOptions); diff --git a/src/core/Darwin.zig b/src/core/Darwin.zig index 1808272c..d3ff6d10 100644 --- a/src/core/Darwin.zig +++ b/src/core/Darwin.zig @@ -2,7 +2,6 @@ const std = @import("std"); const mach = @import("../main.zig"); const Core = @import("../Core.zig"); const InputState = @import("InputState.zig"); -const Frequency = @import("Frequency.zig"); const unicode = @import("unicode.zig"); const detectBackendType = @import("common.zig").detectBackendType; const gpu = mach.gpu; diff --git a/src/core/Null.zig b/src/core/Null.zig index 5aec6582..2a6fb34b 100644 --- a/src/core/Null.zig +++ b/src/core/Null.zig @@ -5,7 +5,6 @@ const std = @import("std"); const mach = @import("../main.zig"); const Core = @import("../Core.zig"); const InputState = @import("InputState.zig"); -const Frequency = @import("Frequency.zig"); const unicode = @import("unicode.zig"); const detectBackendType = @import("common.zig").detectBackendType; const gpu = mach.gpu; diff --git a/src/core/Timer.zig b/src/core/Timer.zig deleted file mode 100644 index 820fd59e..00000000 --- a/src/core/Timer.zig +++ /dev/null @@ -1,57 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const PlatformTimer = if (builtin.cpu.arch == .wasm32) @panic("TODO: support WASM") else NativeTimer; - -const Timer = @This(); - -platform: PlatformTimer, - -/// Initialize the timer. -pub fn start() !Timer { - return .{ .platform = try PlatformTimer.start() }; -} - -/// Reads the timer value since start or the last reset in nanoseconds. -pub inline fn readPrecise(timer: *Timer) u64 { - return timer.platform.read(); -} - -/// Reads the timer value since start or the last reset in seconds. -pub inline fn read(timer: *Timer) f32 { - return @as(f32, @floatFromInt(timer.readPrecise())) / @as(f32, @floatFromInt(std.time.ns_per_s)); -} - -/// Resets the timer value to 0/now. -pub inline fn reset(timer: *Timer) void { - timer.platform.reset(); -} - -/// Returns the current value of the timer in nanoseconds, then resets it. -pub inline fn lapPrecise(timer: *Timer) u64 { - return timer.platform.lap(); -} - -/// Returns the current value of the timer in seconds, then resets it. -pub inline fn lap(timer: *Timer) f32 { - return @as(f32, @floatFromInt(timer.lapPrecise())) / @as(f32, @floatFromInt(std.time.ns_per_s)); -} - -const NativeTimer = struct { - timer: std.time.Timer, - - pub fn start() !NativeTimer { - return .{ .timer = try std.time.Timer.start() }; - } - - pub inline fn read(timer: *NativeTimer) u64 { - return timer.timer.read(); - } - - pub inline fn reset(timer: *NativeTimer) void { - timer.timer.reset(); - } - - pub inline fn lap(timer: *NativeTimer) u64 { - return timer.timer.lap(); - } -}; diff --git a/src/core/win32.zig b/src/core/win32.zig index 74e5ef3c..9cf9489f 100644 --- a/src/core/win32.zig +++ b/src/core/win32.zig @@ -3,7 +3,6 @@ const w = @import("win32/win32.zig"); const mach = @import("../main.zig"); const Core = @import("../Core.zig"); const InputState = @import("InputState.zig"); -const Frequency = @import("Frequency.zig"); const unicode = @import("unicode.zig"); const gpu = mach.gpu; diff --git a/src/main.zig b/src/main.zig index 37a858f9..23b2ca33 100644 --- a/src/main.zig +++ b/src/main.zig @@ -4,7 +4,6 @@ const std = @import("std"); // Core pub const Core = if (build_options.want_core) @import("Core.zig") else struct {}; -pub const Timer = if (build_options.want_core) Core.Timer else struct {}; // Mach standard library // gamemode requires libc on linux @@ -13,6 +12,7 @@ pub const gfx = if (build_options.want_mach) @import("gfx/main.zig") else struct pub const Audio = if (build_options.want_sysaudio) @import("Audio.zig") else struct {}; pub const math = @import("math/main.zig"); pub const testing = @import("testing.zig"); +pub const time = @import("time/main.zig"); pub const sysaudio = if (build_options.want_sysaudio) @import("sysaudio/main.zig") else struct {}; pub const sysgpu = if (build_options.want_sysgpu) @import("sysgpu/main.zig") else struct {}; @@ -57,6 +57,7 @@ test { _ = gfx; _ = math; _ = testing; + _ = time; std.testing.refAllDeclsRecursive(@import("module/Archetype.zig")); std.testing.refAllDeclsRecursive(@import("module/entities.zig")); // std.testing.refAllDeclsRecursive(@import("module/main.zig")); diff --git a/src/core/Frequency.zig b/src/time/Frequency.zig similarity index 87% rename from src/core/Frequency.zig rename to src/time/Frequency.zig index 7d6b275b..7054b44d 100644 --- a/src/core/Frequency.zig +++ b/src/time/Frequency.zig @@ -1,4 +1,4 @@ -const std = @import("std"); +const mach = @import("../main.zig"); const Timer = @import("Timer.zig"); pub const Frequency = @This(); @@ -38,21 +38,21 @@ pub inline fn tick(f: *Frequency) void { if (f.delta_time) |delta_time| { f.delta_time_ns.* = current_time -| f.internal.last_time; - delta_time.* = @as(f32, @floatFromInt(f.delta_time_ns.*)) / @as(f32, @floatFromInt(std.time.ns_per_s)); + delta_time.* = @as(f32, @floatFromInt(f.delta_time_ns.*)) / @as(f32, @floatFromInt(mach.time.ns_per_s)); } - if (current_time >= std.time.ns_per_s) { + if (current_time >= mach.time.ns_per_s) { f.rate = f.internal.count; f.internal.count = 0; f.internal.timer.reset(); - current_time -= std.time.ns_per_s; + current_time -= mach.time.ns_per_s; } f.internal.last_time = current_time; f.internal.count += 1; if (f.target != 0) { const limited_count = @min(f.target, f.internal.count); - const target_time_per_tick: u64 = (std.time.ns_per_s / f.target); + const target_time_per_tick: u64 = (mach.time.ns_per_s / f.target); const target_time = target_time_per_tick * limited_count; if (current_time > target_time) { f.delay_ns = 0; diff --git a/src/time/Timer.zig b/src/time/Timer.zig new file mode 100644 index 00000000..916d4f6b --- /dev/null +++ b/src/time/Timer.zig @@ -0,0 +1,38 @@ +const mach = @import("../main.zig"); +const std = @import("std"); + +const Timer = @This(); + +// TODO: support a WASM-based timer as well, which is the primary reason this abstraction exists. + +timer: std.time.Timer, + +/// Initialize the timer. +pub fn start() !Timer { + return .{ .timer = try std.time.Timer.start() }; +} + +/// Reads the timer value since start or the last reset in nanoseconds. +pub inline fn readPrecise(timer: *Timer) u64 { + return timer.timer.read(); +} + +/// Reads the timer value since start or the last reset in seconds. +pub inline fn read(timer: *Timer) f32 { + return @as(f32, @floatFromInt(timer.readPrecise())) / @as(f32, @floatFromInt(mach.time.ns_per_s)); +} + +/// Resets the timer value to 0/now. +pub inline fn reset(timer: *Timer) void { + timer.timer.reset(); +} + +/// Returns the current value of the timer in nanoseconds, then resets it. +pub inline fn lapPrecise(timer: *Timer) u64 { + return timer.timer.lap(); +} + +/// Returns the current value of the timer in seconds, then resets it. +pub inline fn lap(timer: *Timer) f32 { + return @as(f32, @floatFromInt(timer.lapPrecise())) / @as(f32, @floatFromInt(mach.time.ns_per_s)); +} diff --git a/src/time/main.zig b/src/time/main.zig new file mode 100644 index 00000000..75de3661 --- /dev/null +++ b/src/time/main.zig @@ -0,0 +1,11 @@ +pub const std = @import("std"); + +pub const ns_per_s = std.time.ns_per_s; + +pub const Timer = @import("Timer.zig"); +pub const Frequency = @import("Frequency.zig"); + +test { + _ = Timer; + _ = Frequency; +}