203 lines
5.9 KiB
Zig
203 lines
5.9 KiB
Zig
const std = @import("std");
|
|
|
|
const zaudio = @import("zaudio");
|
|
const zglfw = @import("zglfw");
|
|
const zgpu = @import("zgpu");
|
|
const zgui = @import("zgui");
|
|
const ztracy = @import("ztracy");
|
|
|
|
const game = @import("game.zig");
|
|
const Log = @import("Log.zig");
|
|
|
|
pub const min_framerate = 30.0;
|
|
pub const min_frametime = 1.0 / min_framerate;
|
|
pub const min_window_height = 360;
|
|
pub const min_window_width = 640;
|
|
pub const temp_allocator_capacity = 16 * 1024 * 1024;
|
|
pub const window_title = "voxel-game";
|
|
|
|
pub var allocator: std.mem.Allocator = undefined;
|
|
pub var audio_engine: *zaudio.Engine = undefined;
|
|
pub var gctx: *zgpu.GraphicsContext = undefined;
|
|
pub var logs: std.ArrayListUnmanaged(Log) = undefined;
|
|
pub var temp_allocator: std.mem.Allocator = undefined;
|
|
pub var window: *zglfw.Window = undefined;
|
|
|
|
pub const std_options: std.Options = .{
|
|
.logFn = logFn,
|
|
};
|
|
|
|
pub fn main() !void {
|
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
defer _ = gpa.deinit();
|
|
|
|
var ta = ztracy.TracyAllocator.init(gpa.allocator());
|
|
|
|
var fba = std.heap.FixedBufferAllocator.init(&struct {
|
|
pub var buffer: [temp_allocator_capacity]u8 = undefined;
|
|
}.buffer);
|
|
|
|
allocator = ta.allocator();
|
|
temp_allocator = fba.threadSafeAllocator();
|
|
|
|
defer {
|
|
for (logs.items) |log| {
|
|
allocator.free(log.message);
|
|
}
|
|
logs.deinit(allocator);
|
|
}
|
|
|
|
// --- zaudio --------------------------------------------------------------
|
|
|
|
const zone_init_zaudio = ztracy.ZoneN(@src(), "Init zaudio");
|
|
|
|
zaudio.init(allocator);
|
|
defer zaudio.deinit();
|
|
|
|
audio_engine = try zaudio.Engine.create(null);
|
|
defer audio_engine.destroy();
|
|
|
|
zone_init_zaudio.End();
|
|
|
|
// --- zglfw ---------------------------------------------------------------
|
|
|
|
const zone_init_zglfw = ztracy.ZoneN(@src(), "Init zglfw");
|
|
|
|
try zglfw.init();
|
|
defer zglfw.terminate();
|
|
|
|
const monitor = zglfw.getPrimaryMonitor() orelse return error.PrimaryMonitorNotFound;
|
|
const video_mode = try monitor.getVideoMode();
|
|
|
|
zglfw.windowHint(.client_api, .no_api);
|
|
window = try zglfw.Window.create(video_mode.width, video_mode.height, window_title, monitor);
|
|
window.setSizeLimits(
|
|
min_window_width,
|
|
min_window_height,
|
|
-1,
|
|
-1,
|
|
);
|
|
defer window.destroy();
|
|
|
|
std.debug.assert(zglfw.setCharCallback(window, game.charCallback) == null);
|
|
std.debug.assert(zglfw.setCursorPosCallback(window, game.cursorPosCallback) == null);
|
|
std.debug.assert(zglfw.setKeyCallback(window, game.keyCallback) == null);
|
|
std.debug.assert(zglfw.setMouseButtonCallback(window, game.mouseButtonCallback) == null);
|
|
std.debug.assert(zglfw.setScrollCallback(window, game.scrollCallback) == null);
|
|
|
|
zone_init_zglfw.End();
|
|
|
|
// --- zgpu ----------------------------------------------------------------
|
|
|
|
const zone_init_zgpu = ztracy.ZoneN(@src(), "Init zgpu");
|
|
|
|
gctx = try zgpu.GraphicsContext.create(allocator, .{
|
|
.window = window,
|
|
.fn_getTime = @ptrCast(&zglfw.getTime),
|
|
.fn_getFramebufferSize = @ptrCast(&zglfw.Window.getFramebufferSize),
|
|
.fn_getWin32Window = @ptrCast(&zglfw.getWin32Window),
|
|
.fn_getX11Display = @ptrCast(&zglfw.getX11Display),
|
|
.fn_getX11Window = @ptrCast(&zglfw.getX11Window),
|
|
.fn_getWaylandDisplay = @ptrCast(&zglfw.getWaylandDisplay),
|
|
.fn_getWaylandSurface = @ptrCast(&zglfw.getWaylandWindow),
|
|
.fn_getCocoaWindow = @ptrCast(&zglfw.getCocoaWindow),
|
|
}, .{});
|
|
defer gctx.destroy(allocator);
|
|
|
|
zone_init_zgpu.End();
|
|
|
|
// --- zgui ----------------------------------------------------------------
|
|
|
|
const zone_init_zgui = ztracy.ZoneN(@src(), "Init zgui");
|
|
|
|
zgui.init(allocator);
|
|
defer zgui.deinit();
|
|
|
|
zgui.backend.init(
|
|
window,
|
|
gctx.device,
|
|
@intFromEnum(zgpu.GraphicsContext.swapchain_format),
|
|
@intFromEnum(zgpu.wgpu.TextureFormat.undef),
|
|
);
|
|
defer zgui.backend.deinit();
|
|
|
|
zgui.io.setIniFilename(null);
|
|
|
|
zone_init_zgui.End();
|
|
|
|
// --- game ----------------------------------------------------------------
|
|
|
|
const zone_init_game = ztracy.ZoneN(@src(), "Init game");
|
|
|
|
try game.init();
|
|
defer game.deinit();
|
|
|
|
zone_init_game.End();
|
|
|
|
// --- main loop -----------------------------------------------------------
|
|
|
|
const zone_main_loop = ztracy.ZoneN(@src(), "Main loop");
|
|
|
|
var t2 = zglfw.getTime();
|
|
|
|
while (!window.shouldClose()) {
|
|
ztracy.FrameMark();
|
|
|
|
fba.reset();
|
|
|
|
const t1 = zglfw.getTime();
|
|
const dt: f32 = @floatCast(@max(t2 - t1, min_frametime));
|
|
t2 = t1;
|
|
|
|
zglfw.pollEvents();
|
|
zgui.backend.newFrame(
|
|
gctx.swapchain_descriptor.width,
|
|
gctx.swapchain_descriptor.height,
|
|
);
|
|
|
|
game.update(dt);
|
|
|
|
const swapchain_texture_view = gctx.swapchain.getCurrentTextureView();
|
|
defer swapchain_texture_view.release();
|
|
|
|
const commands = commands: {
|
|
const encoder = gctx.device.createCommandEncoder(null);
|
|
defer encoder.release();
|
|
|
|
{
|
|
const pass = zgpu.beginRenderPassSimple(
|
|
encoder,
|
|
.load,
|
|
swapchain_texture_view,
|
|
null,
|
|
null,
|
|
null,
|
|
);
|
|
defer zgpu.endReleasePass(pass);
|
|
zgui.backend.draw(pass);
|
|
}
|
|
|
|
break :commands encoder.finish(null);
|
|
};
|
|
defer commands.release();
|
|
|
|
gctx.submit(&.{commands});
|
|
_ = gctx.present();
|
|
}
|
|
|
|
zone_main_loop.End();
|
|
}
|
|
|
|
fn logFn(
|
|
comptime level: std.log.Level,
|
|
comptime _: @Type(.enum_literal),
|
|
comptime fmt: []const u8,
|
|
args: anytype,
|
|
) void {
|
|
const message = std.fmt.allocPrint(allocator, fmt, args) catch return;
|
|
logs.append(allocator, Log.init(level, message)) catch {
|
|
allocator.free(message);
|
|
return;
|
|
};
|
|
}
|