Update Zig to use the new Writergate version (#1664)

For reference: https://github.com/ziglang/zig/pull/24329

some commits have been extracted from #1583, but the x86_64 backend has
been disabled due to its horrible performance.

Remaining work:
- [x] Wait for official builds on ziglang.org and upload them to our
repository
- [x] Add workaround for https://github.com/ziglang/zig/pull/24466
- [x] Fix TODO comment about ANSI support in stdout
- [x] Check for compile-time performance changes → it went from 13.1 to
11.9 seconds 🎉
This commit is contained in:
IntegratedQuantum 2025-07-15 23:00:29 +02:00 committed by GitHub
parent 6811f21682
commit aae66ea77f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
29 changed files with 135 additions and 120 deletions

View File

@ -14,11 +14,12 @@ jobs:
name: Compilation Check
steps:
- uses: actions/checkout@v3
- uses: mlugg/setup-zig@v1
- uses: mlugg/setup-zig@v2
with:
version: 0.14.0
version: 0.15.0-dev.1034+bd97b6618
- run: sudo apt install libgl-dev libasound2-dev libx11-dev glslang-tools
- run: wget -O /opt/hostedtoolcache/zig/0.14.0/x64/lib/std/zig/render.zig https://github.com/PixelGuys/Cubyz-std-lib/releases/download/0.14.0/render.zig
- run: echo "zigPath=$(command -v zig | sed 's/.\{3\}$//')" >> $GITHUB_ENV
- run: wget -O $zigPath/lib/std/zig/render.zig https://github.com/PixelGuys/Cubyz-std-lib/releases/download/0.15.0-dev.1034+bd97b6618/render.zig
- run: zig build
- run: zig build -Dtarget=x86_64-windows-gnu
- run: zig build test

View File

@ -1 +1 @@
0.14.0
0.15.0-dev.1034+bd97b6618

View File

@ -52,6 +52,7 @@ fn linkLibraries(b: *std.Build, exe: *std.Build.Step.Compile, useLocalDeps: bool
exe.addObjectFile(subPath.path(b, libName(b, "SPIRV-Tools-opt", t)));
if(t.os.tag == .windows) {
exe.linkSystemLibrary("crypt32");
exe.linkSystemLibrary("gdi32");
exe.linkSystemLibrary("opengl32");
exe.linkSystemLibrary("ws2_32");
@ -168,15 +169,19 @@ pub fn build(b: *std.Build) !void {
.install_dir = .{.custom = ".."},
});
const exe = b.addExecutable(.{
.name = "Cubyzig",
const mainModule = b.addModule("main", .{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
//.sanitize_thread = true,
//.use_llvm = false,
});
exe.root_module.addImport("main", exe.root_module);
const exe = b.addExecutable(.{
.name = "Cubyzig",
.root_module = mainModule,
//.sanitize_thread = true,
.use_llvm = true,
});
exe.root_module.addImport("main", mainModule);
try addModFeatures(b, exe);
linkLibraries(b, exe, useLocalDeps);
@ -193,13 +198,11 @@ pub fn build(b: *std.Build) !void {
run_step.dependOn(&run_cmd.step);
const exe_tests = b.addTest(.{
.root_source_file = b.path("src/main.zig"),
.root_module = mainModule,
.test_runner = .{.path = b.path("test/runner.zig"), .mode = .simple},
.target = target,
.optimize = optimize,
});
linkLibraries(b, exe_tests, useLocalDeps);
exe_tests.root_module.addImport("main", exe_tests.root_module);
exe_tests.root_module.addImport("main", mainModule);
try addModFeatures(b, exe_tests);
const run_exe_tests = b.addRunArtifact(exe_tests);
@ -210,16 +213,14 @@ pub fn build(b: *std.Build) !void {
const formatter = b.addExecutable(.{
.name = "CubyzigFormatter",
.root_module = b.addModule("format", .{
.root_source_file = b.path("src/formatter/format.zig"),
.target = target,
.optimize = optimize,
}),
});
// ZLS is stupid and cannot detect which executable is the main one, so we add the import everywhere...
formatter.root_module.addAnonymousImport("main", .{
.target = target,
.optimize = optimize,
.root_source_file = b.path("src/main.zig"),
});
formatter.root_module.addImport("main", mainModule);
const formatter_install = b.addInstallArtifact(formatter, .{});
@ -234,16 +235,14 @@ pub fn build(b: *std.Build) !void {
const zig_fmt = b.addExecutable(.{
.name = "zig_fmt",
.root_module = b.addModule("fmt", .{
.root_source_file = b.path("src/formatter/fmt.zig"),
.target = target,
.optimize = optimize,
}),
});
// ZLS is stupid and cannot detect which executable is the main one, so we add the import everywhere...
zig_fmt.root_module.addAnonymousImport("main", .{
.target = target,
.optimize = optimize,
.root_source_file = b.path("src/main.zig"),
});
zig_fmt.root_module.addImport("main", mainModule);
const zig_fmt_install = b.addInstallArtifact(zig_fmt, .{});

View File

@ -33,7 +33,7 @@ then
esac
fi
VERSION=zig-$OS-$ARCH-$BASE_VERSION
VERSION=zig-$ARCH-$OS-$BASE_VERSION
mkdir -p compiler/zig
touch compiler/version.txt

View File

@ -14,7 +14,7 @@ IF "%arch%"=="" (
set arch=x86_64
)
set version=zig-windows-%arch%-%baseVersion%
set version=zig-%arch%-windows-%baseVersion%
if not exist compiler mkdir compiler
if not exist compiler\version.txt copy NUL compiler\version.txt >NUL

View File

@ -309,7 +309,7 @@ pub const Sync = struct { // MARK: Sync
const typ = try reader.readEnum(Command.PayloadType);
@setEvalBranchQuota(100000);
const payload: Command.Payload = switch(typ) {
inline else => |_typ| @unionInit(Command.Payload, @tagName(_typ), try std.meta.FieldType(Command.Payload, _typ).deserialize(reader, .server, source)),
inline else => |_typ| @unionInit(Command.Payload, @tagName(_typ), try @FieldType(Command.Payload, @tagName(_typ)).deserialize(reader, .server, source)),
};
executeCommand(payload, source);
}
@ -2001,7 +2001,7 @@ pub fn save(self: Inventory, allocator: NeverFailingAllocator) ZonElement {
for(self._items, 0..) |stack, i| {
if(!stack.empty()) {
var buf: [1024]u8 = undefined;
zonObject.put(buf[0..std.fmt.formatIntBuf(&buf, i, 10, .lower, .{})], stack.store(allocator));
zonObject.put(buf[0..std.fmt.printInt(&buf, i, 10, .lower, .{})], stack.store(allocator));
}
}
return zonObject;
@ -2011,7 +2011,7 @@ pub fn loadFromZon(self: Inventory, zon: ZonElement) void {
for(self._items, 0..) |*stack, i| {
stack.clear();
var buf: [1024]u8 = undefined;
const stackZon = zon.getChild(buf[0..std.fmt.formatIntBuf(&buf, i, 10, .lower, .{})]);
const stackZon = zon.getChild(buf[0..std.fmt.printInt(&buf, i, 10, .lower, .{})]);
if(stackZon == .object) {
stack.item = Item.init(stackZon) catch |err| {
const msg = stackZon.toStringEfficient(main.stackAllocator, "");

View File

@ -644,7 +644,7 @@ pub fn loadWorldAssets(assetFolder: []const u8, blockPalette: *Palette, itemPale
break :blk null;
}) |addon| {
if(addon.kind == .directory) {
const path = std.fmt.allocPrintZ(main.stackAllocator.allocator, "assets/{s}/blocks/textures", .{addon.name}) catch unreachable;
const path = std.fmt.allocPrintSentinel(main.stackAllocator.allocator, "assets/{s}/blocks/textures", .{addon.name}, 0) catch unreachable;
defer main.stackAllocator.free(path);
std.fs.cwd().access(path, .{}) catch continue;
main.utils.file_monitor.listenToPath(path, main.blocks.meshes.reloadTextures, 0);
@ -680,7 +680,7 @@ pub fn unloadAssets() void { // MARK: unloadAssets()
break :blk null;
}) |addon| {
if(addon.kind == .directory) {
const path = std.fmt.allocPrintZ(main.stackAllocator.allocator, "assets/{s}/blocks/textures", .{addon.name}) catch unreachable;
const path = std.fmt.allocPrintSentinel(main.stackAllocator.allocator, "assets/{s}/blocks/textures", .{addon.name}, 0) catch unreachable;
defer main.stackAllocator.free(path);
std.fs.cwd().access(path, .{}) catch continue;
main.utils.file_monitor.removePath(path);

View File

@ -27,11 +27,11 @@ const AudioData = struct {
};
const addon = id[0..colonIndex];
const fileName = id[colonIndex + 1 ..];
const path1 = std.fmt.allocPrintZ(main.stackAllocator.allocator, "assets/{s}/music/{s}.ogg", .{addon, fileName}) catch unreachable;
const path1 = std.fmt.allocPrintSentinel(main.stackAllocator.allocator, "assets/{s}/music/{s}.ogg", .{addon, fileName}, 0) catch unreachable;
defer main.stackAllocator.free(path1);
var err: c_int = 0;
if(c.stb_vorbis_open_filename(path1.ptr, &err, null)) |ogg_stream| return ogg_stream;
const path2 = std.fmt.allocPrintZ(main.stackAllocator.allocator, "serverAssets/{s}/music/{s}.ogg", .{addon, fileName}) catch unreachable;
const path2 = std.fmt.allocPrintSentinel(main.stackAllocator.allocator, "serverAssets/{s}/music/{s}.ogg", .{addon, fileName}, 0) catch unreachable;
defer main.stackAllocator.free(path2);
if(c.stb_vorbis_open_filename(path2.ptr, &err, null)) |ogg_stream| return ogg_stream;
std.log.err("Couldn't find music with id \"{s}\". Searched path \"{s}\" and \"{s}\"", .{id, path1, path2});
@ -309,7 +309,7 @@ fn miniaudioCallback(
output: ?*anyopaque,
input: ?*const anyopaque,
frameCount: u32,
) callconv(.C) void {
) callconv(.c) void {
_ = input;
_ = maDevice;
const valuesPerBuffer = 2*frameCount; // Stereo

View File

@ -7,7 +7,15 @@ pub fn main() !void {
}
// zig fmt: off
/// Everything below is a direct copy of fmt.zig from the zig compiler
/// Everything below is a direct copy of src/fmt.zig from the zig compiler
const std = @import("std");
const mem = std.mem;
const fs = std.fs;
const process = std.process;
const Allocator = std.mem.Allocator;
const Color = std.zig.Color;
const fatal = std.process.fatal;
const usage_fmt =
\\Usage: zig fmt [file]...
@ -63,7 +71,7 @@ pub fn run(
const arg = args[i];
if (mem.startsWith(u8, arg, "-")) {
if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
const stdout = std.io.getStdOut().writer();
const stdout = std.fs.File.stdout().deprecatedWriter();
try stdout.writeAll(usage_fmt);
return process.cleanExit();
} else if (mem.eql(u8, arg, "--color")) {
@ -104,7 +112,7 @@ pub fn run(
fatal("cannot use --stdin with positional arguments", .{});
}
const stdin = std.io.getStdIn();
const stdin: fs.File = .stdin();
const source_code = std.zig.readSourceFileToEndAlloc(gpa, stdin, null) catch |err| {
fatal("unable to read stdin: {}", .{err});
};
@ -157,7 +165,7 @@ pub fn run(
process.exit(code);
}
return std.io.getStdOut().writeAll(formatted);
return std.fs.File.stdout().writeAll(formatted);
}
if (input_files.items.len == 0) {
@ -213,6 +221,7 @@ const FmtError = error{
DestinationAddressRequired,
DiskQuota,
FileTooBig,
MessageTooBig,
InputOutput,
NoSpaceLeft,
AccessDenied,
@ -373,7 +382,7 @@ fn fmtPathFile(
return;
if (check_mode) {
const stdout = std.io.getStdOut().writer();
const stdout = std.fs.File.stdout().deprecatedWriter();
try stdout.print("{s}\n", .{file_path});
fmt.any_error = true;
} else {
@ -382,15 +391,7 @@ fn fmtPathFile(
try af.file.writeAll(fmt.out_buffer.items);
try af.finish();
const stdout = std.io.getStdOut().writer();
const stdout = std.fs.File.stdout().deprecatedWriter();
try stdout.print("{s}\n", .{file_path});
}
}
const std = @import("std");
const mem = std.mem;
const fs = std.fs;
const process = std.process;
const Allocator = std.mem.Allocator;
const Color = std.zig.Color;
const fatal = std.process.fatal;

View File

@ -1900,6 +1900,7 @@ pub fn LargeBuffer(comptime Entry: type) type { // MARK: LargerBuffer
}
pub fn init(self: *Self, allocator: NeverFailingAllocator, size: u31, binding: c_uint) void {
self.used = 0;
self.binding = binding;
self.createBuffer(size);
self.activeFence = 0;
@ -2512,7 +2513,7 @@ pub const Image = struct { // MARK: Image
pub fn readFromFile(allocator: NeverFailingAllocator, path: []const u8) !Image {
var result: Image = undefined;
var channel: c_int = undefined;
const nullTerminatedPath = std.fmt.allocPrintZ(main.stackAllocator.allocator, "{s}", .{path}) catch unreachable; // TODO: Find a more zig-friendly image loading library.
const nullTerminatedPath = main.stackAllocator.dupeZ(u8, path); // TODO: Find a more zig-friendly image loading library.
errdefer main.stackAllocator.free(nullTerminatedPath);
stb_image.stbi_set_flip_vertically_on_load(1);
const data = stb_image.stbi_load(nullTerminatedPath.ptr, @ptrCast(&result.width), @ptrCast(&result.height), &channel, 4) orelse {
@ -2526,7 +2527,7 @@ pub const Image = struct { // MARK: Image
pub fn readUnflippedFromFile(allocator: NeverFailingAllocator, path: []const u8) !Image {
var result: Image = undefined;
var channel: c_int = undefined;
const nullTerminatedPath = std.fmt.allocPrintZ(main.stackAllocator.allocator, "{s}", .{path}) catch unreachable; // TODO: Find a more zig-friendly image loading library.
const nullTerminatedPath = main.stackAllocator.dupeZ(u8, path); // TODO: Find a more zig-friendly image loading library.
errdefer main.stackAllocator.free(nullTerminatedPath);
const data = stb_image.stbi_load(nullTerminatedPath.ptr, @ptrCast(&result.width), @ptrCast(&result.height), &channel, 4) orelse {
return error.FileNotFound;

View File

@ -434,10 +434,10 @@ pub const Key = struct { // MARK: Key
};
pub const GLFWCallbacks = struct { // MARK: GLFWCallbacks
fn errorCallback(errorCode: c_int, description: [*c]const u8) callconv(.C) void {
fn errorCallback(errorCode: c_int, description: [*c]const u8) callconv(.c) void {
std.log.err("GLFW Error({}): {s}", .{errorCode, description});
}
fn keyCallback(_: ?*c.GLFWwindow, glfw_key: c_int, scancode: c_int, action: c_int, _mods: c_int) callconv(.C) void {
fn keyCallback(_: ?*c.GLFWwindow, glfw_key: c_int, scancode: c_int, action: c_int, _mods: c_int) callconv(.c) void {
const mods: Key.Modifiers = @bitCast(@as(u6, @intCast(_mods)));
if(!mods.control and main.gui.selectedTextInput != null and c.glfwGetKeyName(glfw_key, scancode) != null) return; // Don't send events for keys that are used in writing letters.
const isGrabbed = grabbed;
@ -465,13 +465,13 @@ pub const GLFWCallbacks = struct { // MARK: GLFWCallbacks
}
}
}
fn charCallback(_: ?*c.GLFWwindow, codepoint: c_uint) callconv(.C) void {
fn charCallback(_: ?*c.GLFWwindow, codepoint: c_uint) callconv(.c) void {
if(!grabbed) {
main.gui.textCallbacks.char(@intCast(codepoint));
}
}
pub fn framebufferSize(_: ?*c.GLFWwindow, newWidth: c_int, newHeight: c_int) callconv(.C) void {
pub fn framebufferSize(_: ?*c.GLFWwindow, newWidth: c_int, newHeight: c_int) callconv(.c) void {
std.log.info("Framebuffer: {}, {}", .{newWidth, newHeight});
width = @intCast(newWidth);
height = @intCast(newHeight);
@ -485,7 +485,7 @@ pub const GLFWCallbacks = struct { // MARK: GLFWCallbacks
var deltaBufferPosition: u2 = 0;
var currentPos: Vec2f = Vec2f{0, 0};
var ignoreDataAfterRecentGrab: bool = true;
fn cursorPosition(_: ?*c.GLFWwindow, x: f64, y: f64) callconv(.C) void {
fn cursorPosition(_: ?*c.GLFWwindow, x: f64, y: f64) callconv(.c) void {
const newPos = Vec2f{
@floatCast(x),
@floatCast(y),
@ -509,7 +509,7 @@ pub const GLFWCallbacks = struct { // MARK: GLFWCallbacks
currentPos = newPos;
lastUsedMouse = true;
}
fn mouseButton(_: ?*c.GLFWwindow, button: c_int, action: c_int, _mods: c_int) callconv(.C) void {
fn mouseButton(_: ?*c.GLFWwindow, button: c_int, action: c_int, _mods: c_int) callconv(.c) void {
const mods: Key.Modifiers = @bitCast(@as(u6, @intCast(_mods)));
const isGrabbed = grabbed;
if(action == c.GLFW_PRESS or action == c.GLFW_RELEASE) {
@ -526,11 +526,11 @@ pub const GLFWCallbacks = struct { // MARK: GLFWCallbacks
}
}
}
fn scroll(_: ?*c.GLFWwindow, xOffset: f64, yOffset: f64) callconv(.C) void {
fn scroll(_: ?*c.GLFWwindow, xOffset: f64, yOffset: f64) callconv(.c) void {
_ = xOffset;
scrollOffset += @floatCast(yOffset);
}
fn glDebugOutput(source: c_uint, typ: c_uint, _: c_uint, severity: c_uint, length: c_int, message: [*c]const u8, _: ?*const anyopaque) callconv(.C) void {
fn glDebugOutput(source: c_uint, typ: c_uint, _: c_uint, severity: c_uint, length: c_int, message: [*c]const u8, _: ?*const anyopaque) callconv(.c) void {
const sourceString: []const u8 = switch(source) {
c.GL_DEBUG_SOURCE_API => "API",
c.GL_DEBUG_SOURCE_APPLICATION => "Application",

View File

@ -168,12 +168,12 @@ fn moveCursorLeft(self: *TextInput, mods: main.Window.Key.Modifiers) void {
if(self.cursor.? == 0) return;
self.cursor.? -= 1;
// Find end of previous "word":
while(!std.ascii.isAlphabetic(text[self.cursor.?]) and std.ascii.isASCII(text[self.cursor.?])) {
while(!std.ascii.isAlphabetic(text[self.cursor.?]) and std.ascii.isAscii(text[self.cursor.?])) {
if(self.cursor.? == 0) return;
self.cursor.? -= 1;
}
// Find the start of the previous "word":
while(std.ascii.isAlphabetic(text[self.cursor.?]) or !std.ascii.isASCII(text[self.cursor.?])) {
while(std.ascii.isAlphabetic(text[self.cursor.?]) or !std.ascii.isAscii(text[self.cursor.?])) {
if(self.cursor.? == 0) return;
self.cursor.? -= 1;
}
@ -213,12 +213,12 @@ fn moveCursorRight(self: *TextInput, mods: main.Window.Key.Modifiers) void {
if(mods.control) {
const text = self.currentString.items;
// Find start of next "word":
while(!std.ascii.isAlphabetic(text[self.cursor.?]) and std.ascii.isASCII(text[self.cursor.?])) {
while(!std.ascii.isAlphabetic(text[self.cursor.?]) and std.ascii.isAscii(text[self.cursor.?])) {
self.cursor.? += 1;
if(self.cursor.? >= self.currentString.items.len) return;
}
// Find the end of the next "word":
while(std.ascii.isAlphabetic(text[self.cursor.?]) or !std.ascii.isASCII(text[self.cursor.?])) {
while(std.ascii.isAlphabetic(text[self.cursor.?]) or !std.ascii.isAscii(text[self.cursor.?])) {
self.cursor.? += 1;
if(self.cursor.? >= self.currentString.items.len) return;
}

View File

@ -30,7 +30,7 @@ const width: f32 = 420;
fn discoverIpAddress() void {
main.server.connectionManager.makeOnline();
ipAddress = std.fmt.allocPrint(main.globalAllocator.allocator, "{}", .{main.server.connectionManager.externalAddress}) catch unreachable;
ipAddress = std.fmt.allocPrint(main.globalAllocator.allocator, "{f}", .{main.server.connectionManager.externalAddress}) catch unreachable;
gotIpAddress.store(true, .release);
}

View File

@ -41,7 +41,7 @@ pub fn onOpen() void {
row.add(Label.init(.{0, 0}, 200, connection.user.?.name, .left));
row.add(Button.initText(.{0, 0}, 100, "Kick", .{.callback = @ptrCast(&kick), .arg = @intFromPtr(connection)}));
} else {
const ip = std.fmt.allocPrint(main.stackAllocator.allocator, "{}", .{connection.remoteAddress}) catch unreachable;
const ip = std.fmt.allocPrint(main.stackAllocator.allocator, "{f}", .{connection.remoteAddress}) catch unreachable;
defer main.stackAllocator.free(ip);
row.add(Label.init(.{0, 0}, 200, ip, .left));
row.add(Button.initText(.{0, 0}, 100, "Cancel", .{.callback = @ptrCast(&kick), .arg = @intFromPtr(connection)}));

View File

@ -34,7 +34,7 @@ fn discoverIpAddress() void {
ipAddress = main.globalAllocator.dupe(u8, @errorName(err));
return;
};
ipAddress = std.fmt.allocPrint(main.globalAllocator.allocator, "{}", .{connection.?.externalAddress}) catch unreachable;
ipAddress = std.fmt.allocPrint(main.globalAllocator.allocator, "{f}", .{connection.?.externalAddress}) catch unreachable;
gotIpAddress.store(true, .release);
}

View File

@ -62,7 +62,7 @@ pub fn openWorld(name: []const u8) void {
};
while(!main.server.running.load(.acquire)) {
std.time.sleep(1_000_000);
std.Thread.sleep(1_000_000);
}
clientConnection.world = &main.game.testWorld;
const ipPort = std.fmt.allocPrint(main.stackAllocator.allocator, "127.0.0.1:{}", .{main.server.connectionManager.localPort}) catch unreachable;

View File

@ -265,11 +265,10 @@ pub const JsonElement = union(JsonType) { // MARK: JsonElement
fn recurseToString(json: JsonElement, list: *List(u8), tabs: u32, comptime visualCharacters: bool) void {
switch(json) {
.JsonInt => |value| {
std.fmt.formatInt(value, 10, .lower, .{}, list.writer()) catch unreachable;
list.writer().print("{d}", .{value}) catch unreachable;
},
.JsonFloat => |value| {
var buf: [std.fmt.format_float.bufferSize(.scientific, @TypeOf(value))]u8 = undefined;
list.appendSlice(std.fmt.format_float.formatFloat(&buf, value, .{.mode = .scientific}) catch unreachable);
list.writer().print("{e}", .{value}) catch unreachable;
},
.JsonBool => |value| {
if(value) {

View File

@ -231,7 +231,7 @@ fn initLogging() void {
return;
};
supportsANSIColors = std.io.getStdOut().supportsAnsiEscapeCodes();
supportsANSIColors = std.fs.File.stdout().supportsAnsiEscapeCodes();
}
fn deinitLogging() void {
@ -264,7 +264,9 @@ fn logToStdErr(comptime format: []const u8, args: anytype) void {
const string = std.fmt.allocPrint(allocator, format, args) catch format;
defer allocator.free(string);
nosuspend std.io.getStdErr().writeAll(string) catch {};
const writer = std.debug.lockStderrWriter(&.{});
defer std.debug.unlockStderrWriter();
nosuspend writer.writeAll(string) catch {};
}
// MARK: Callbacks
@ -682,7 +684,7 @@ pub fn main() void { // MARK: main()
c.glClear(c.GL_DEPTH_BUFFER_BIT | c.GL_STENCIL_BUFFER_BIT | c.GL_COLOR_BUFFER_BIT);
gui.windowlist.gpu_performance_measuring.stopQuery();
} else {
std.time.sleep(16_000_000);
std.Thread.sleep(16_000_000);
}
const endRendering = std.time.nanoTimestamp();
@ -696,7 +698,7 @@ pub fn main() void { // MARK: main()
if(settings.fpsCap) |fpsCap| {
const minFrameTime = @divFloor(1000*1000*1000, fpsCap);
const sleep = @min(minFrameTime, @max(0, minFrameTime - (endRendering -% lastBeginRendering)));
std.time.sleep(sleep);
std.Thread.sleep(sleep);
}
const begin = std.time.nanoTimestamp();
const deltaTime = @as(f64, @floatFromInt(begin -% lastBeginRendering))/1e9;

View File

@ -64,11 +64,20 @@ const Socket = struct {
.port = @byteSwap(destination.port),
.addr = destination.ip,
};
if(builtin.os.tag == .windows) { // TODO: Upstream error, fix after next Zig update after #24466 is merged
const result = posix.system.sendto(self.socketID, data.ptr, data.len, 0, @ptrCast(&addr), @sizeOf(posix.sockaddr.in));
if(result < 0) {
std.log.info("Got error while sending to {f}: {s}", .{destination, @tagName(std.os.windows.ws2_32.WSAGetLastError())});
} else {
std.debug.assert(@as(usize, @intCast(result)) == data.len);
}
} else {
std.debug.assert(data.len == posix.sendto(self.socketID, data, 0, @ptrCast(&addr), @sizeOf(posix.sockaddr.in)) catch |err| {
std.log.info("Got error while sending to {}: {s}", .{destination, @errorName(err)});
std.log.info("Got error while sending to {f}: {s}", .{destination, @errorName(err)});
return;
});
}
}
fn receive(self: Socket, buffer: []u8, timeout: i32, resultAddress: *Address) ![]u8 {
if(builtin.os.tag == .windows) { // Of course Windows always has it's own special thing.
@ -85,7 +94,7 @@ const Socket = struct {
else => |err| return std.os.windows.unexpectedWSAError(err),
}
} else if(length == 0) {
std.time.sleep(1000000); // Manually sleep, since WSAPoll is blocking.
std.Thread.sleep(1000000); // Manually sleep, since WSAPoll is blocking.
return error.Timeout;
}
} else {
@ -139,7 +148,7 @@ pub const Address = struct {
pub const localHost = 0x0100007f;
pub fn format(self: Address, _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
pub fn format(self: Address, writer: anytype) !void {
if(self.isSymmetricNAT) {
try writer.print("{}.{}.{}.{}:?{}", .{self.ip & 255, self.ip >> 8 & 255, self.ip >> 16 & 255, self.ip >> 24, self.port});
} else {
@ -295,7 +304,7 @@ const STUN = struct { // MARK: STUN
continue;
};
if(oldAddress) |other| {
std.log.info("{}", .{result});
std.log.info("{f}", .{result});
if(other.ip == result.ip and other.port == result.port) {
return result;
} else {
@ -556,17 +565,17 @@ pub const ConnectionManager = struct { // MARK: ConnectionManager
}
if(self.allowNewConnections.load(.monotonic) or source.ip == Address.localHost) {
if(data.len != 0 and data[0] == @intFromEnum(Connection.ChannelId.init)) {
const ip = std.fmt.allocPrint(main.stackAllocator.allocator, "{}", .{source}) catch unreachable;
const ip = std.fmt.allocPrint(main.stackAllocator.allocator, "{f}", .{source}) catch unreachable;
defer main.stackAllocator.free(ip);
const user = main.server.User.initAndIncreaseRefCount(main.server.connectionManager, ip) catch |err| {
std.log.err("Cannot connect user from external IP {}: {s}", .{source, @errorName(err)});
std.log.err("Cannot connect user from external IP {f}: {s}", .{source, @errorName(err)});
return;
};
user.decreaseRefCount();
}
} else {
// TODO: Reduce the number of false alarms in the short period after a disconnect.
std.log.warn("Unknown connection from address: {}", .{source});
std.log.warn("Unknown connection from address: {f}", .{source});
std.log.debug("Message: {any}", .{data});
}
}
@ -2025,7 +2034,7 @@ pub const Connection = struct { // MARK: Connection
self.tryReceive(data) catch |err| {
std.log.err("Got error while processing received network data: {s}", .{@errorName(err)});
if(@errorReturnTrace()) |trace| {
std.log.info("{}", .{trace});
std.log.info("{f}", .{trace});
}
self.disconnect();
};
@ -2218,7 +2227,7 @@ pub const Connection = struct { // MARK: Connection
self.manager.send(&.{@intFromEnum(ChannelId.disconnect)}, self.remoteAddress, null);
self.connectionState.store(.disconnectDesired, .unordered);
if(builtin.os.tag == .windows and !self.isServerSide() and main.server.world != null) {
std.time.sleep(10000000); // Windows is too eager to close the socket, without waiting here we get a ConnectionResetByPeer on the other side.
std.Thread.sleep(10000000); // Windows is too eager to close the socket, without waiting here we get a ConnectionResetByPeer on the other side.
}
self.manager.removeConnection(self);
if(self.user) |user| {

View File

@ -1717,7 +1717,7 @@ pub const ChunkMesh = struct { // MARK: ChunkMesh
}
self.culledSortingCount += @intCast(self.blockBreakingFaces.items.len);
// Upload:
faceBuffers[std.math.log2_int(u32, self.pos.voxelSize)].uploadData(self.sortingOutputBuffer[0..self.culledSortingCount], &self.transparentMesh.bufferAllocation);
faceBuffers[self.transparentMesh.lod].uploadData(self.sortingOutputBuffer[0..self.culledSortingCount], &self.transparentMesh.bufferAllocation);
self.uploadChunkPosition();
}

View File

@ -444,7 +444,7 @@ pub fn start(name: []const u8, port: ?u16) void {
while(running.load(.monotonic)) {
const newTime = std.time.nanoTimestamp();
if(newTime -% lastTime < updateNanoTime) {
std.time.sleep(@intCast(lastTime +% updateNanoTime -% newTime));
std.Thread.sleep(@intCast(lastTime +% updateNanoTime -% newTime));
lastTime +%= updateNanoTime;
} else {
std.log.warn("The server is lagging behind by {d:.1} ms", .{@as(f32, @floatFromInt(newTime -% lastTime -% updateNanoTime))/1000000.0});

View File

@ -48,7 +48,7 @@ pub const RegionFile = struct { // MARK: RegionFile
defer main.stackAllocator.free(data);
self.load(path, data) catch {
std.log.err("Corrupted region file: {s}", .{path});
if(@errorReturnTrace()) |trace| std.log.info("{}", .{trace});
if(@errorReturnTrace()) |trace| std.log.info("{f}", .{trace});
};
return self;
}

View File

@ -751,7 +751,7 @@ pub const ServerWorld = struct { // MARK: ServerWorld
updateRequest.region.decreaseRefCount();
}
self.mutex.unlock();
std.time.sleep(1_000_000);
std.Thread.sleep(1_000_000);
self.mutex.lock();
if(main.threadPool.queueSize() == 0 and self.chunkUpdateQueue.peek() == null and self.regionUpdateQueue.peek() == null) break;
}

View File

@ -655,7 +655,7 @@ pub fn BlockingMaxHeap(comptime T: type) type { // MARK: BlockingMaxHeap
self.waitingThreads.broadcast();
while(self.waitingThreadCount != 0) {
self.mutex.unlock();
std.time.sleep(1000000);
std.Thread.sleep(1000000);
self.mutex.lock();
}
self.mutex.unlock();
@ -899,7 +899,7 @@ pub const ThreadPool = struct { // MARK: ThreadPool
// Wait for active tasks:
for(self.currentTasks) |*task| {
while(task.load(.monotonic) == vtable) {
std.time.sleep(1e6);
std.Thread.sleep(1e6);
}
}
}
@ -966,7 +966,7 @@ pub const ThreadPool = struct { // MARK: ThreadPool
break;
}
}
std.time.sleep(1000000);
std.Thread.sleep(1000000);
}
}
@ -998,7 +998,7 @@ pub fn DynamicPackedIntArray(size: comptime_int) type { // MARK: DynamicPackedIn
pub fn initCapacity(bitSize: u5) Self {
std.debug.assert(bitSize == 0 or bitSize & bitSize - 1 == 0); // Must be a power of 2
return .{
.data = dynamicIntArrayAllocator.allocator().alignedAlloc(u32, 64, @as(usize, @divExact(size, @bitSizeOf(u32)))*bitSize),
.data = dynamicIntArrayAllocator.allocator().alignedAlloc(u32, .@"64", @as(usize, @divExact(size, @bitSizeOf(u32)))*bitSize),
.bitSize = bitSize,
};
}

View File

@ -98,7 +98,7 @@ const LinuxImpl = struct { // MARK: LinuxImpl
return;
}) |entry| {
if(entry.kind == .directory) {
const subPath = std.fmt.allocPrintZ(main.stackAllocator.allocator, "{s}/{s}", .{path, entry.name}) catch unreachable;
const subPath = std.fmt.allocPrintSentinel(main.stackAllocator.allocator, "{s}/{s}", .{path, entry.name}, 0) catch unreachable;
defer main.stackAllocator.free(subPath);
addWatchDescriptor(info, subPath);
addWatchDescriptorsRecursive(info, subPath);

View File

@ -17,7 +17,7 @@ pub const StackAllocator = struct { // MARK: StackAllocator
pub fn init(backingAllocator: NeverFailingAllocator, size: u31) StackAllocator {
return .{
.backingAllocator = backingAllocator,
.buffer = backingAllocator.alignedAlloc(u8, 4096, size),
.buffer = backingAllocator.alignedAlloc(u8, .fromByteUnits(4096), size),
.index = 0,
};
}
@ -341,9 +341,9 @@ pub const NeverFailingAllocator = struct { // MARK: NeverFailingAllocator
self: NeverFailingAllocator,
comptime T: type,
/// null means naturally aligned
comptime alignment: ?u29,
comptime alignment: ?Alignment,
n: usize,
) []align(alignment orelse @alignOf(T)) T {
) []align(if(alignment) |a| a.toByteUnits() else @alignOf(T)) T {
return self.allocator.alignedAlloc(T, alignment, n) catch unreachable;
}
@ -351,10 +351,10 @@ pub const NeverFailingAllocator = struct { // MARK: NeverFailingAllocator
self: NeverFailingAllocator,
comptime T: type,
/// null means naturally aligned
comptime alignment: ?u29,
comptime alignment: ?Alignment,
n: usize,
return_address: usize,
) []align(alignment orelse @alignOf(T)) T {
) []align(if(alignment) |a| a.toByteUnits() else @alignOf(T)) T {
return self.allocator.allocAdvancedWithRetAddr(T, alignment, n, return_address) catch unreachable;
}
@ -483,6 +483,7 @@ pub const NeverFailingArenaAllocator = struct { // MARK: NeverFailingArena
}
pub fn shrinkAndFree(self: *NeverFailingArenaAllocator) void {
if(true) return;
const node = self.arena.state.buffer_list.first orelse return;
const allocBuf = @as([*]u8, @ptrCast(node))[0..node.data];
const dataSize = std.mem.alignForward(usize, @sizeOf(std.SinglyLinkedList(usize).Node) + self.arena.state.end_index, @alignOf(std.SinglyLinkedList(usize).Node));
@ -570,7 +571,7 @@ pub fn MemoryPool(Item: type) type { // MARK: MemoryPool
main.utils.assertLocked(&pool.mutex);
pool.totalAllocations += 1;
pool.freeAllocations += 1;
const mem = pool.arena.allocator().alignedAlloc(u8, item_alignment, item_size);
const mem = pool.arena.allocator().alignedAlloc(u8, .fromByteUnits(item_alignment), item_size);
return mem[0..item_size]; // coerce slice to array pointer
}
};
@ -634,7 +635,7 @@ pub fn PowerOfTwoPoolAllocator(minSize: comptime_int, maxSize: comptime_int, max
fn allocNew(self: *Bucket, arena: NeverFailingAllocator, size: usize) [*]align(alignment) u8 {
self.totalAllocations += 1;
self.freeAllocations += 1;
return arena.alignedAlloc(u8, alignment, size).ptr;
return arena.alignedAlloc(u8, .fromByteUnits(alignment), size).ptr;
}
};

View File

@ -213,7 +213,7 @@ pub fn List(comptime T: type) type {
@compileError("The Writer interface is only defined for ArrayList(u8) " ++
"but the given type is ArrayList(" ++ @typeName(T) ++ ")")
else
std.io.Writer(*@This(), error{}, appendWrite);
std.io.GenericWriter(*@This(), error{}, appendWrite);
pub fn writer(self: *@This()) Writer {
return .{.context = self};

View File

@ -351,11 +351,10 @@ pub const ZonElement = union(enum) { // MARK: Zon
fn recurseToString(zon: ZonElement, list: *List(u8), tabs: u32, comptime visualCharacters: bool) void {
switch(zon) {
.int => |value| {
std.fmt.formatInt(value, 10, .lower, .{}, list.writer()) catch unreachable;
list.writer().print("{d}", .{value}) catch unreachable;
},
.float => |value| {
var buf: [std.fmt.format_float.bufferSize(.scientific, @TypeOf(value))]u8 = undefined;
list.appendSlice(std.fmt.format_float.formatFloat(&buf, value, .{.mode = .scientific}) catch unreachable);
list.writer().print("{e}", .{value}) catch unreachable;
},
.bool => |value| {
if(value) {

View File

@ -1,5 +1,5 @@
//! Default test runner for unit tests.
// Source: https://github.com/ziglang/zig/blob/0.14.0/lib/compiler/test_runner.zig
//! Default test runner for unit tests.
const builtin = @import("builtin");
const std = @import("std");
@ -16,7 +16,9 @@ var fba_buffer: [8192]u8 = undefined;
var fba = std.heap.FixedBufferAllocator.init(&fba_buffer);
const crippled = switch(builtin.zig_backend) {
.stage2_riscv64 => true,
.stage2_powerpc,
.stage2_riscv64,
=> true,
else => false,
};
@ -68,8 +70,8 @@ fn mainServer() !void {
@disableInstrumentation();
var server = try std.zig.Server.init(.{
.gpa = fba.allocator(),
.in = std.io.getStdIn(),
.out = std.io.getStdOut(),
.in = .stdin(),
.out = .stdout(),
.zig_version = builtin.zig_version_string,
});
defer server.deinit();
@ -189,7 +191,7 @@ fn mainTerminal() void {
.root_name = "Test",
.estimated_total_items = test_fn_list.len,
});
const doColors = std.io.getStdErr().supportsAnsiEscapeCodes();
const doColors = std.fs.File.stderr().supportsAnsiEscapeCodes();
const reset = if(doColors) "\x1b[0m" else "";
const red = if(doColors) "\x1b[31m" else "";
const yellow = if(doColors) "\x1b[33m" else "";
@ -283,6 +285,7 @@ pub fn mainSimple() anyerror!void {
};
// is the backend capable of using std.fmt.format to print a summary at the end?
const print_summary = switch(builtin.zig_backend) {
.stage2_riscv64 => true,
else => false,
};
@ -291,7 +294,7 @@ pub fn mainSimple() anyerror!void {
var failed: u64 = 0;
// we don't want to bring in File and Writer if the backend doesn't support it
const stderr = if(comptime enable_print) std.io.getStdErr() else {};
const stderr = if(comptime enable_print) std.fs.File.stderr() else {};
for(builtin.test_functions) |test_fn| {
if(test_fn.func()) |_| {
@ -300,7 +303,7 @@ pub fn mainSimple() anyerror!void {
stderr.writeAll("... ") catch {};
stderr.writeAll("PASS\n") catch {};
}
} else |err| if(enable_print) {
} else |err| {
if(enable_print) {
stderr.writeAll(test_fn.name) catch {};
stderr.writeAll("... ") catch {};
@ -318,7 +321,7 @@ pub fn mainSimple() anyerror!void {
passed += 1;
}
if(enable_print and print_summary) {
stderr.writer().print("{} passed, {} skipped, {} failed\n", .{passed, skipped, failed}) catch {};
stderr.deprecatedWriter().print("{} passed, {} skipped, {} failed\n", .{passed, skipped, failed}) catch {};
}
if(failed != 0) std.process.exit(1);
}
@ -343,7 +346,7 @@ var is_fuzz_test: bool = undefined;
extern fn fuzzer_set_name(name_ptr: [*]const u8, name_len: usize) void;
extern fn fuzzer_init(cache_dir: FuzzerSlice) void;
extern fn fuzzer_init_corpus_elem(input_ptr: [*]const u8, input_len: usize) void;
extern fn fuzzer_start(testOne: *const fn([*]const u8, usize) callconv(.C) void) void;
extern fn fuzzer_start(testOne: *const fn([*]const u8, usize) callconv(.c) void) void;
extern fn fuzzer_coverage_id() u64;
pub fn fuzz(
@ -375,7 +378,7 @@ pub fn fuzz(
const global = struct {
var ctx: @TypeOf(context) = undefined;
fn fuzzer_one(input_ptr: [*]const u8, input_len: usize) callconv(.C) void {
fn fuzzer_one(input_ptr: [*]const u8, input_len: usize) callconv(.c) void {
@disableInstrumentation();
testing.allocator_instance = .{};
defer if(testing.allocator_instance.deinit() == .leak) std.process.exit(1);