Skip to content

Commit 33f6807

Browse files
committed
Migrate to Zig 0.16.0-dev.2535 Io-based APIs
1 parent 9b59bbc commit 33f6807

12 files changed

Lines changed: 135 additions & 106 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ compiler/
1111
*.txt
1212
nul
1313
/cache
14+
/zig-pkg

.vscode/tasks.json

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,32 @@
11
{
2-
"version": "2.0.0",
3-
"tasks": [
4-
{
5-
"label": "Build",
6-
"type": "shell",
7-
"command": "./compiler/zig/zig.exe",
8-
"args": ["build"],
9-
"group": {
10-
"kind": "build",
11-
"isDefault": true
12-
},
13-
"problemMatcher": []
14-
},
15-
{
16-
"label": "Build and Run",
17-
"type": "shell",
18-
"command": "./compiler/zig/zig.exe",
19-
"args": ["build", "run"],
20-
"group": "build",
21-
"problemMatcher": []
22-
},
23-
{
24-
"label": "Build and Run (Tracy)",
25-
"type": "shell",
26-
"command": "./compiler/zig/zig.exe",
27-
"args": ["build", "run", "-Dtracy=true"],
28-
"group": "build",
29-
"problemMatcher": []
30-
}
31-
]
2+
"version": "2.0.0",
3+
"tasks": [
4+
{
5+
"label": "Build",
6+
"type": "shell",
7+
"command": "zig",
8+
"args": ["build"],
9+
"group": {
10+
"kind": "build",
11+
"isDefault": true
12+
},
13+
"problemMatcher": []
14+
},
15+
{
16+
"label": "Build and Run",
17+
"type": "shell",
18+
"command": "zig",
19+
"args": ["build", "run"],
20+
"group": "build",
21+
"problemMatcher": []
22+
},
23+
{
24+
"label": "Build and Run (Tracy)",
25+
"type": "shell",
26+
"command": "zig",
27+
"args": ["build", "run", "-Dtracy=true"],
28+
"group": "build",
29+
"problemMatcher": []
30+
}
31+
]
3232
}

.zigversion

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.16.0-dev.2368+380ea6fb5
1+
0.16.0-dev.2535+b5bd49460

build.zig.zon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
.name = .FarHorizons,
33
.version = "0.0.0",
44
.fingerprint = 0x953f10b5d0f3e503,
5-
.minimum_zig_version = "0.16.0-dev.1484+d0ba6642b",
5+
.minimum_zig_version = "0.16.0-dev.2535+b5bd49460",
66
.dependencies = .{
77
// Headers (shared across all platforms)
88
.farhorizons_deps_headers = .{

src/client/FarHorizonsClient.zig

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -224,10 +224,7 @@ pub const FarHorizonsClient = struct {
224224
self.window.show();
225225

226226
var esc_was_pressed = false;
227-
var timer = std.time.Timer.start() catch {
228-
logger.err("Failed to start timer", .{});
229-
return;
230-
};
227+
var last_frame_time = Io.Clock.awake.now(self.io);
231228
var tick_accumulator: f64 = 0;
232229

233230
self.ecs_world = ecs.World.init(self.allocator);
@@ -302,7 +299,9 @@ pub const FarHorizonsClient = struct {
302299
const frame_zone = profiler.traceNamed("Frame");
303300
defer frame_zone.end();
304301

305-
const delta_ns = timer.lap();
302+
const now_time = Io.Clock.awake.now(self.io);
303+
const delta_ns: u64 = @intCast(last_frame_time.durationTo(now_time).nanoseconds);
304+
last_frame_time = now_time;
306305
const delta_ms: f64 = @as(f64, @floatFromInt(delta_ns)) / 1_000_000.0;
307306
tick_accumulator += delta_ms;
308307

src/client/renderer/ShaderManager.zig

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ pub const ShaderManager = struct {
6868
var hotbar_icon_frag: ?[]u8 = null;
6969

7070
if (enable_runtime_compilation) {
71-
var total_timer = std.time.Timer.start() catch unreachable;
71+
const total_start = Io.Clock.awake.now(io);
7272

7373
compiler = try ShaderCompiler.init(allocator, io);
7474

@@ -77,17 +77,17 @@ pub const ShaderManager = struct {
7777

7878
// Compile default shaders at startup from assets directory
7979
logger.info("Compiling default vertex shader...", .{});
80-
var vert_timer = std.time.Timer.start() catch unreachable;
80+
const vert_start = Io.Clock.awake.now(io);
8181
var vert_compiled = try compiler.?.compileFile(default_shader_path ++ "triangle.vert");
82-
const vert_time_us = vert_timer.read() / std.time.ns_per_us;
82+
const vert_time_us = @as(u64, @intCast(@divTrunc(vert_start.durationTo(Io.Clock.awake.now(io)).nanoseconds, std.time.ns_per_us)));
8383
default_vert = try allocator.dupe(u8, vert_compiled.spv_data);
8484
vert_compiled.deinit();
8585
logger.info("Vertex shader compiled in {d}us ({d} bytes SPIR-V)", .{ vert_time_us, default_vert.?.len });
8686

8787
logger.info("Compiling default fragment shader...", .{});
88-
var frag_timer = std.time.Timer.start() catch unreachable;
88+
const frag_start = Io.Clock.awake.now(io);
8989
var frag_compiled = try compiler.?.compileFile(default_shader_path ++ "triangle.frag");
90-
const frag_time_us = frag_timer.read() / std.time.ns_per_us;
90+
const frag_time_us = @as(u64, @intCast(@divTrunc(frag_start.durationTo(Io.Clock.awake.now(io)).nanoseconds, std.time.ns_per_us)));
9191
default_frag = try allocator.dupe(u8, frag_compiled.spv_data);
9292
frag_compiled.deinit();
9393
logger.info("Fragment shader compiled in {d}us ({d} bytes SPIR-V)", .{ frag_time_us, default_frag.?.len });
@@ -155,7 +155,8 @@ pub const ShaderManager = struct {
155155
hotbar_icon_frag_compiled.deinit();
156156
logger.info("Hotbar icon shaders compiled", .{});
157157

158-
const total_time_ms = @as(f64, @floatFromInt(total_timer.read())) / @as(f64, std.time.ns_per_ms);
158+
const total_elapsed_ns: i64 = @intCast(total_start.durationTo(Io.Clock.awake.now(io)).nanoseconds);
159+
const total_time_ms = @as(f64, @floatFromInt(total_elapsed_ns)) / @as(f64, std.time.ns_per_ms);
159160
const cache_stats = compiler.?.getCacheStats();
160161
logger.info("Shader loading complete in {d:.2}ms (cache: {d} hits, {d} misses)", .{
161162
total_time_ms,

src/client/renderer/buffer/ChunkBufferManager.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/// ChunkBufferManager - Coordinates vertex/index arenas for chunk rendering
22
/// Uses growable buffer arenas for AAA-quality smooth frame times
33
const std = @import("std");
4+
const Io = std.Io;
45
const volk = @import("volk");
56
const vk = volk.c;
67
const shared = @import("Shared");
@@ -102,6 +103,7 @@ pub const ChunkBufferManager = struct {
102103
device: vk.VkDevice,
103104
physical_device: vk.VkPhysicalDevice,
104105
config: ChunkBufferConfig,
106+
io: Io,
105107
) !Self {
106108
logger.info("Initializing ChunkBufferManager (single-buffer mode for GPU-driven rendering)...", .{});
107109
logger.info(" Vertex buffer: {} MB, Index buffer: {} MB", .{
@@ -123,6 +125,7 @@ pub const ChunkBufferManager = struct {
123125
.alignment = config.vertex_size,
124126
.expansion_threshold_percent = 100, // Disable expansion threshold
125127
},
128+
io,
126129
);
127130
errdefer vertex_arena.deinit();
128131

@@ -139,6 +142,7 @@ pub const ChunkBufferManager = struct {
139142
.alignment = config.index_size,
140143
.expansion_threshold_percent = 100, // Disable expansion threshold
141144
},
145+
io,
142146
);
143147
errdefer index_arena.deinit();
144148

src/client/renderer/buffer/GrowableBufferArena.zig

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
/// - Async background expansion when capacity threshold reached
77
/// - Batched rendering support (groups draw calls by buffer)
88
const std = @import("std");
9+
const Io = std.Io;
910
const volk = @import("volk");
1011
const vk = volk.c;
1112
const shared = @import("Shared");
@@ -66,9 +67,12 @@ pub const GrowableBufferArena = struct {
6667
/// Async expansion state
6768
expansion_thread: ?std.Thread = null,
6869
pending_arena: ?BufferArena = null,
69-
expansion_mutex: std.Thread.Mutex = .{},
70+
expansion_mutex: Io.Mutex = Io.Mutex.init,
7071
expansion_failed: bool = false,
7172

73+
/// I/O subsystem (needed for mutex operations)
74+
io: Io,
75+
7276
/// Vulkan handles needed for creating new arenas
7377
device: vk.VkDevice,
7478
physical_device: vk.VkPhysicalDevice,
@@ -90,13 +94,15 @@ pub const GrowableBufferArena = struct {
9094
device: vk.VkDevice,
9195
physical_device: vk.VkPhysicalDevice,
9296
config: GrowableBufferConfig,
97+
io: Io,
9398
) !Self {
9499
var self = Self{
95100
.arenas = .{},
96101
.device = device,
97102
.physical_device = physical_device,
98103
.config = config,
99104
.allocator = allocator,
105+
.io = io,
100106
};
101107

102108
// Pre-allocate initial arenas
@@ -137,6 +143,7 @@ pub const GrowableBufferArena = struct {
137143
usage: vk.VkBufferUsageFlags,
138144
alignment: u64,
139145
avg_chunk_size: u64,
146+
io: Io,
140147
) !Self {
141148
// Calculate expected chunk count
142149
const h_chunks = @as(u64, view_distance) * 2 + 1;
@@ -171,7 +178,7 @@ pub const GrowableBufferArena = struct {
171178
.initial_arena_count = @intCast(initial_arenas),
172179
.usage = usage,
173180
.alignment = alignment,
174-
});
181+
}, io);
175182
}
176183

177184
pub fn deinit(self: *Self) void {
@@ -335,23 +342,23 @@ pub const GrowableBufferArena = struct {
335342
self.config.alignment,
336343
) catch |err| {
337344
logger.err("Async arena allocation failed: {}", .{err});
338-
self.expansion_mutex.lock();
345+
self.expansion_mutex.lockUncancelable(self.io);
339346
self.expansion_failed = true;
340-
self.expansion_mutex.unlock();
347+
self.expansion_mutex.unlock(self.io);
341348
return;
342349
};
343350

344-
self.expansion_mutex.lock();
351+
self.expansion_mutex.lockUncancelable(self.io);
345352
self.pending_arena = new_arena;
346-
self.expansion_mutex.unlock();
353+
self.expansion_mutex.unlock(self.io);
347354

348355
logger.info("Async arena allocation complete", .{});
349356
}
350357

351358
/// Collect a pending arena if ready
352359
fn collectPendingArena(self: *Self) void {
353-
self.expansion_mutex.lock();
354-
defer self.expansion_mutex.unlock();
360+
self.expansion_mutex.lockUncancelable(self.io);
361+
defer self.expansion_mutex.unlock(self.io);
355362

356363
if (self.pending_arena) |arena| {
357364
self.arenas.append(self.allocator, arena) catch |err| {

src/client/world/ChunkManager.zig

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -300,10 +300,10 @@ pub const ChunkManager = struct {
300300
.chunk_storage = storage,
301301
.pending_loads = PosSet.init(allocator),
302302
.managed_positions = PosSet.init(allocator),
303-
.completed_queue = ThreadSafeQueue(CompletedMesh).init(allocator),
304-
.completed_terrain = ThreadSafeQueue(TerrainResult).init(allocator),
303+
.completed_queue = ThreadSafeQueue(CompletedMesh).init(allocator, io),
304+
.completed_terrain = ThreadSafeQueue(TerrainResult).init(allocator, io),
305305
.pending_mesh = PosSet.init(allocator),
306-
.pool = try ThreadPool.init(allocator, config.worker_count, processTask),
306+
.pool = try ThreadPool.init(allocator, io, config.worker_count, processTask),
307307
.player_chunk = ChunkPos{ .x = 0, .z = 0, .section_y = 0 },
308308
.config = config,
309309
.render_system = render_system,
@@ -326,6 +326,7 @@ pub const ChunkManager = struct {
326326
// Uses single-buffer mode by default (1GB vertex, 512MB index)
327327
// Required for GPU-driven rendering where all geometry must be in one buffer
328328
},
329+
self.io,
329330
);
330331
self.buffer_manager = buffer_mgr;
331332

@@ -352,7 +353,7 @@ pub const ChunkManager = struct {
352353
logger.info("Model cache pre-warmed", .{});
353354

354355
const rcu_instance = try self.allocator.create(Rcu);
355-
rcu_instance.* = Rcu.init(self.allocator, self.config.worker_count);
356+
rcu_instance.* = Rcu.init(self.allocator, self.config.worker_count, self.io);
356357
self.rcu = rcu_instance;
357358
logger.info("RCU initialized for {} worker threads", .{self.config.worker_count});
358359

0 commit comments

Comments
 (0)