almost finished update to Zig 0.16.0
Some checks failed
Build / build (push) Successful in 2m18s
Test / build_and_test (push) Failing after 6m9s

This commit is contained in:
2026-04-18 02:26:29 +02:00
parent d5a520e261
commit e97ee8b23d
23 changed files with 355 additions and 466 deletions

View File

@@ -31,7 +31,7 @@ pool: *CommandPool,
state: State,
begin_info: ?vk.CommandBufferBeginInfo,
host_allocator: VulkanAllocator,
state_mutex: std.Thread.Mutex,
state_mutex: std.Io.Mutex,
vtable: *const VTable,
dispatch_table: *const DispatchTable,
@@ -69,7 +69,7 @@ pub fn init(device: *Device, allocator: std.mem.Allocator, info: *const vk.Comma
.state = .Initial,
.begin_info = null,
.host_allocator = VulkanAllocator.from(allocator).cloneWithScope(.object),
.state_mutex = .{},
.state_mutex = .init,
.vtable = undefined,
.dispatch_table = undefined,
};
@@ -79,8 +79,11 @@ inline fn transitionState(self: *Self, target: State, from_allowed: []const Stat
if (!std.EnumSet(State).initMany(from_allowed).contains(self.state)) {
return error.NotAllowed;
}
self.state_mutex.lock();
defer self.state_mutex.unlock();
const io = self.owner.io();
self.state_mutex.lockUncancelable(io);
defer self.state_mutex.unlock(io);
self.state = target;
}

View File

@@ -1,8 +1,6 @@
const std = @import("std");
const vk = @import("vulkan");
const logger = @import("lib.zig").logger;
const Dispatchable = @import("Dispatchable.zig").Dispatchable;
const NonDispatchable = @import("NonDispatchable.zig").NonDispatchable;
const VulkanAllocator = @import("VulkanAllocator.zig");
@@ -23,6 +21,7 @@ const Event = @import("Event.zig");
const Fence = @import("Fence.zig");
const Framebuffer = @import("Framebuffer.zig");
const Image = @import("Image.zig");
const Instance = @import("Instance.zig");
const ImageView = @import("ImageView.zig");
const Pipeline = @import("Pipeline.zig");
const PipelineCache = @import("PipelineCache.zig");
@@ -35,6 +34,7 @@ const ShaderModule = @import("ShaderModule.zig");
const Self = @This();
pub const ObjectType: vk.ObjectType = .device;
instance: *Instance,
physical_device: *const PhysicalDevice,
queues: std.AutoArrayHashMapUnmanaged(u32, std.ArrayList(*Dispatchable(Queue))),
host_allocator: VulkanAllocator,
@@ -71,9 +71,10 @@ pub const DispatchTable = struct {
destroy: *const fn (*Self, std.mem.Allocator) VkError!void,
};
pub fn init(allocator: std.mem.Allocator, physical_device: *const PhysicalDevice, info: *const vk.DeviceCreateInfo) VkError!Self {
pub fn init(allocator: std.mem.Allocator, instance: *Instance, physical_device: *const PhysicalDevice, info: *const vk.DeviceCreateInfo) VkError!Self {
_ = info;
return .{
.instance = instance,
.physical_device = physical_device,
.queues = .empty,
.host_allocator = VulkanAllocator.from(allocator).clone(),
@@ -99,14 +100,15 @@ pub fn createQueues(self: *Self, allocator: std.mem.Allocator, info: *const vk.D
const queue = try self.vtable.createQueue(allocator, self, queue_info.queue_family_index, @intCast(family_ptr.items.len), queue_info.flags);
logger.getManager().get().indent();
defer logger.getManager().get().unindent();
const dispatchable_queue = try Dispatchable(Queue).wrap(allocator, queue);
family_ptr.append(allocator, dispatchable_queue) catch return VkError.OutOfHostMemory;
}
}
pub fn io(self: *const Self) std.Io {
return self.instance.io();
}
pub inline fn destroy(self: *Self, allocator: std.mem.Allocator) VkError!void {
var it = self.queues.iterator();
while (it.next()) |entry| {

View File

@@ -3,8 +3,6 @@ const builtin = @import("builtin");
const vk = @import("vulkan");
const config = @import("config");
const ThreadSafeLoggerManager = @import("logger/ThreadSafeManager.zig");
const VkError = @import("error_set.zig").VkError;
const Dispatchable = @import("Dispatchable.zig").Dispatchable;
const PhysicalDevice = @import("PhysicalDevice.zig");
@@ -29,15 +27,13 @@ const DeviceAllocator = struct {
};
physical_devices: std.ArrayList(*Dispatchable(PhysicalDevice)),
threaded: std.Io.Threaded,
allocator: if (config.debug_allocator) std.heap.DebugAllocator(.{}) else DeviceAllocator,
logger: ThreadSafeLoggerManager,
dispatch_table: *const DispatchTable,
vtable: *const VTable,
pub const VTable = struct {
releasePhysicalDevices: *const fn (*Self, std.mem.Allocator) VkError!void,
requestPhysicalDevices: *const fn (*Self, std.mem.Allocator) VkError!void,
io: *const fn (*Self) std.Io,
};
pub const DispatchTable = struct {
@@ -47,20 +43,11 @@ pub const DispatchTable = struct {
pub fn init(allocator: std.mem.Allocator, infos: *const vk.InstanceCreateInfo) VkError!Self {
_ = allocator;
_ = infos;
var self: Self = .{
return .{
.physical_devices = .empty,
.threaded = undefined,
.allocator = if (config.debug_allocator) .init else .{},
.logger = undefined,
.dispatch_table = undefined,
.vtable = undefined,
};
self.threaded = .init(self.allocator.allocator(), .{});
self.logger = .init(self.threaded.io(), self.allocator.allocator());
return self;
}
/// Dummy for docs creation and stuff
@@ -104,9 +91,6 @@ pub fn releasePhysicalDevices(self: *Self, allocator: std.mem.Allocator) VkError
}
pub fn requestPhysicalDevices(self: *Self, allocator: std.mem.Allocator) VkError!void {
logger.getManager().get().indent();
defer logger.getManager().get().unindent();
try self.vtable.requestPhysicalDevices(self, allocator);
if (self.physical_devices.items.len == 0) {
std.log.scoped(.vkCreateInstance).err("No VkPhysicalDevice found", .{});
@@ -116,3 +100,7 @@ pub fn requestPhysicalDevices(self: *Self, allocator: std.mem.Allocator) VkError
std.log.scoped(.vkCreateInstance).debug("Found VkPhysicalDevice named {s}", .{physical_device.object.props.device_name});
}
}
pub fn io(self: *Self) std.Io {
return self.vtable.io(self);
}

View File

@@ -13,7 +13,7 @@ props: vk.PhysicalDeviceProperties,
mem_props: vk.PhysicalDeviceMemoryProperties,
features: vk.PhysicalDeviceFeatures,
queue_family_props: std.ArrayList(vk.QueueFamilyProperties),
instance: *const Instance,
instance: *Instance,
dispatch_table: *const DispatchTable,
pub const DispatchTable = struct {
@@ -25,7 +25,7 @@ pub const DispatchTable = struct {
release: *const fn (*Self, std.mem.Allocator) VkError!void,
};
pub fn init(allocator: std.mem.Allocator, instance: *const Instance) VkError!Self {
pub fn init(allocator: std.mem.Allocator, instance: *Instance) VkError!Self {
_ = allocator;
return .{
.props = .{

View File

@@ -9,7 +9,7 @@ pub const vku = @cImport({
pub const errors = @import("error_set.zig");
pub const lib_vulkan = @import("lib_vulkan.zig");
pub const logger = @import("logger/logger.zig");
pub const logger = @import("logger.zig");
pub const format = @import("format.zig");
pub const Dispatchable = @import("Dispatchable.zig").Dispatchable;
@@ -92,17 +92,18 @@ pub const LogVerboseLevel = enum {
};
pub fn getLogVerboseLevel() LogVerboseLevel {
const allocator = std.heap.c_allocator;
const level = std.process.getEnvVarOwned(allocator, DRIVER_LOGS_ENV_NAME) catch return .None;
defer allocator.free(level);
return if (std.mem.eql(u8, level, "none"))
.None
else if (std.mem.eql(u8, level, "all"))
.High
else if (std.mem.eql(u8, level, "stupid"))
.TooMuch
else
.Standard;
//const allocator = std.heap.c_allocator;
//const level = std.process.getEnvVarOwned(allocator, DRIVER_LOGS_ENV_NAME) catch return .None;
//defer allocator.free(level);
//return if (std.mem.eql(u8, level, "none"))
// .None
//else if (std.mem.eql(u8, level, "all"))
// .High
//else if (std.mem.eql(u8, level, "stupid"))
// .TooMuch
//else
// .Standard;
return .High;
}
pub inline fn unsupported(comptime fmt: []const u8, args: anytype) void {

View File

@@ -44,22 +44,19 @@ pub const RenderPass = @import("RenderPass.zig");
pub const Sampler = @import("Sampler.zig");
pub const ShaderModule = @import("ShaderModule.zig");
fn entryPointBeginLogTrace(comptime scope: @Type(.enum_literal)) void {
fn entryPointBeginLogTrace(comptime scope: @EnumLiteral()) void {
std.log.scoped(scope).debug("Calling {s}...", .{@tagName(scope)});
logger.getManager().get().indent();
}
fn entryPointEndLogTrace() void {
logger.getManager().get().unindent();
}
fn entryPointEndLogTrace() void {}
fn entryPointNotFoundErrorLog(comptime scope: @Type(.enum_literal), name: []const u8) void {
fn entryPointNotFoundErrorLog(comptime scope: @EnumLiteral(), name: []const u8) void {
if (lib.getLogVerboseLevel() != .TooMuch) return;
std.log.scoped(scope).err("Could not find function {s}", .{name});
}
inline fn notImplementedWarning() void {
logger.nestedFixme("function not yet implemented", .{});
logger.fixme("function not yet implemented", .{});
}
fn functionMapEntryPoint(comptime name: []const u8) struct { []const u8, vk.PfnVoidFunction } {
@@ -342,8 +339,6 @@ pub export fn strollEnumerateInstanceVersion(version: *u32) callconv(vk.vulkan_c
// Instance functions ========================================================================================================================================
pub export fn strollDestroyInstance(p_instance: vk.Instance, callbacks: ?*const vk.AllocationCallbacks) callconv(vk.vulkan_call_conv) void {
defer logger.getManager().deinit();
entryPointBeginLogTrace(.vkDestroyInstance);
defer entryPointEndLogTrace();

118
src/vulkan/logger.zig git.filemode.normal_file
View File

@@ -0,0 +1,118 @@
const std = @import("std");
const builtin = @import("builtin");
const root = @import("root");
const lib = @import("lib.zig");
comptime {
if (!builtin.is_test) {
if (!@hasDecl(root, "DRIVER_NAME")) {
@compileError("Missing DRIVER_NAME in module root");
}
}
}
var mutex: std.Io.Mutex = .init;
pub inline fn fixme(comptime format: []const u8, args: anytype) void {
if (lib.getLogVerboseLevel() == .None) {
return;
}
std.log.scoped(.FIXME).warn("FIXME: " ++ format, args);
}
pub fn log(comptime level: std.log.Level, comptime scope: @EnumLiteral(), comptime format: []const u8, args: anytype) void {
if (lib.getLogVerboseLevel() == .None) {
return;
}
const scope_name = @tagName(scope);
const scope_prefix = comptime blk: {
const limit = 30 - 4;
break :blk if (scope_name.len >= limit)
std.fmt.comptimePrint("({s}...): ", .{scope_name[0..(limit - 3)]})
else
std.fmt.comptimePrint("({s}): ", .{scope_name});
};
const prefix = std.fmt.comptimePrint("{s: <10}", .{"[" ++ comptime level.asText() ++ "] "});
const level_color: std.Io.Terminal.Color = switch (level) {
.info, .debug => .blue,
.warn => .magenta,
.err => .red,
};
const allocator = std.heap.smp_allocator;
var threaded: std.Io.Threaded = .init(allocator, .{});
defer threaded.deinit();
const io = threaded.io();
const stderr_file = std.Io.File.stderr();
const stdout_file = std.Io.File.stdout();
const file = switch (level) {
.info, .debug => stdout_file,
.warn, .err => stderr_file,
};
file.lock(io, .exclusive) catch {};
defer file.unlock(io);
const now = std.Io.Timestamp.now(io, .cpu_process).toMilliseconds();
const now_ms = @mod(now, std.time.ms_per_s);
const now_sec = @mod(@divTrunc(now, std.time.ms_per_s), std.time.s_per_min);
const now_min = @mod(@divTrunc(now, std.time.ms_per_min), 60);
const now_hour = @mod(@divTrunc(now, std.time.ms_per_hour), 24);
var fmt_buffer = std.mem.zeroes([4096]u8);
var fmt_writer = std.Io.Writer.fixed(&fmt_buffer);
fmt_writer.print(format ++ "\n", args) catch {};
fmt_writer.flush() catch return;
mutex.lock(io) catch return;
defer mutex.unlock(io);
var last_pos: usize = 0;
while (std.mem.indexOfScalarPos(u8, &fmt_buffer, last_pos, '\n')) |pos| : (last_pos = pos + 1) {
var buffer = std.mem.zeroes([512]u8);
var file_writer = file.writer(io, &buffer);
var writer = &file_writer.interface;
const term: std.Io.Terminal = .{
.writer = writer,
.mode = std.Io.Terminal.Mode.detect(io, file, false, false) catch return,
};
term.setColor(.magenta) catch {};
writer.print("[StrollDriver ", .{}) catch continue;
if (!builtin.is_test) {
term.setColor(.cyan) catch {};
writer.print(root.DRIVER_NAME, .{}) catch continue;
}
term.setColor(.yellow) catch {};
writer.print(" {d}:{d}:{d}.{d}", .{ now_hour, now_min, now_sec, now_ms }) catch continue;
term.setColor(.magenta) catch {};
writer.print("]", .{}) catch continue;
term.setColor(.cyan) catch {};
writer.print("[Thread {d: >8}]", .{std.Thread.getCurrentId()}) catch continue;
term.setColor(level_color) catch {};
writer.print(prefix, .{}) catch continue;
term.setColor(switch (level) {
.err => .red,
.warn => .magenta,
else => .green,
}) catch {};
writer.print("{s: >30}", .{scope_prefix}) catch continue;
term.setColor(.reset) catch {};
writer.print("{s}\n", .{fmt_buffer[last_pos..pos]}) catch continue;
writer.flush() catch continue;
}
}

View File

@@ -1,41 +0,0 @@
const std = @import("std");
const Self = @This();
pub const Element = struct {
log: [512]u8,
indent_level: usize,
log_level: std.log.Level,
};
stack: std.ArrayList(Element),
allocator: std.mem.Allocator = std.heap.c_allocator,
pub const empty: Self = .{
.stack = .empty,
};
pub fn pushBack(self: *Self, element: Element) !void {
try self.stack.append(self.allocator, element);
}
pub fn popBack(self: *Self) ?Element {
return self.stack.pop();
}
pub fn popFront(self: *Self) Element {
return self.stack.orderedRemove(0);
}
pub fn getLastOrNull(self: *Self) ?Element {
return self.stack.getLastOrNull();
}
pub inline fn len(self: *Self) usize {
return self.stack.items.len;
}
pub fn deinit(self: *Self) void {
self.stack.deinit(self.allocator);
self.* = .empty;
}

View File

@@ -1,54 +0,0 @@
const std = @import("std");
const DebugStack = @import("DebugStack.zig");
const lib = @import("../lib.zig");
const Self = @This();
indent_enabled: bool,
indent_level: usize,
debug_stack: DebugStack,
pub const init: Self = .{
.indent_enabled = true,
.indent_level = 0,
.debug_stack = .empty,
};
pub fn indent(self: *Self) void {
if (lib.getLogVerboseLevel() == .None) {
return;
}
const new_indent_level, const has_overflown = @addWithOverflow(self.indent_level, 1);
if (has_overflown == 0) {
self.indent_level = new_indent_level;
}
}
pub fn unindent(self: *Self) void {
if (lib.getLogVerboseLevel() == .None) {
return;
}
const new_indent_level, const has_overflown = @subWithOverflow(self.indent_level, 1);
if (has_overflown == 0) {
self.indent_level = new_indent_level;
}
loop: while (self.debug_stack.getLastOrNull()) |last| {
if (last.indent_level >= self.indent_level) {
_ = self.debug_stack.popBack();
} else {
break :loop;
}
}
}
pub inline fn enableIndent(self: *Self) void {
self.indent_enabled = true;
}
pub inline fn disableIndent(self: *Self) void {
self.indent_enabled = false;
}
pub inline fn deinit(self: *Self) void {
self.debug_stack.deinit();
}

View File

@@ -1,40 +0,0 @@
const std = @import("std");
const Manager = @import("Manager.zig");
const Self = @This();
managers: std.AutoArrayHashMapUnmanaged(std.Thread.Id, Manager),
allocator: std.mem.Allocator,
mutex: std.Io.Mutex,
io: std.Io,
pub fn init(io: std.Io, allocator: std.mem.Allocator) Self {
return .{
.managers = .empty,
.allocator = allocator,
.mutex = .init,
.io = io,
};
}
pub fn get(self: *Self) *Manager {
const allocator = self.allocator.allocator();
self.mutex.lock();
defer self.mutex.unlock();
return (self.managers.getOrPutValue(allocator, std.Thread.getCurrentId(), .init) catch @panic("Out of memory")).value_ptr;
}
pub fn deinit(self: *Self) void {
self.mutex.lockUncancelable();
defer self.mutex.unlock();
if (self.managers.getPtr(std.Thread.getCurrentId())) |manager| {
manager.deinit();
_ = self.managers.orderedRemove(std.Thread.getCurrentId());
}
if (self.managers.count() == 0) {
self.managers.deinit(self.allocator);
}
}

View File

@@ -1,141 +0,0 @@
//! A instance-level logger that stack in memory all same-indent `debug` logs
//! and only displays them in reverse order if a non-debug log is requested
const std = @import("std");
const builtin = @import("builtin");
const root = @import("root");
const lib = @import("../lib.zig");
const ThreadSafeManager = @import("ThreadSafeManager.zig");
comptime {
if (!builtin.is_test) {
if (!@hasDecl(root, "DRIVER_NAME")) {
@compileError("Missing DRIVER_NAME in module root");
}
}
}
var manager: ThreadSafeManager = .init;
pub inline fn getManager() *ThreadSafeManager {
return &manager;
}
pub inline fn fixme(comptime format: []const u8, args: anytype) void {
if (lib.getLogVerboseLevel() == .None) {
return;
}
getManager().get().disableIndent();
defer getManager().get().enableIndent();
nestedFixme(format, args);
}
pub inline fn nestedFixme(comptime format: []const u8, args: anytype) void {
if (lib.getLogVerboseLevel() == .None) {
return;
}
std.log.scoped(.FIXME).warn("FIXME: " ++ format, args);
}
pub fn log(comptime level: std.log.Level, comptime scope: @EnumLiteral(), comptime format: []const u8, args: anytype) void {
if (lib.getLogVerboseLevel() == .None) {
return;
}
const scope_name = @tagName(scope);
const scope_prefix = comptime blk: {
const limit = 30 - 4;
break :blk if (scope_name.len >= limit)
std.fmt.comptimePrint("({s}...): ", .{scope_name[0..(limit - 3)]})
else
std.fmt.comptimePrint("({s}): ", .{scope_name});
};
const prefix = std.fmt.comptimePrint("{s: <10}", .{"[" ++ comptime level.asText() ++ "] "});
const level_color: std.Io.tty.Color = switch (level) {
.info, .debug => .blue,
.warn => .magenta,
.err => .red,
};
std.debug.lockStdErr();
defer std.debug.unlockStdErr();
var stderr_file = std.fs.File.stderr();
var stdout_file = std.fs.File.stdout();
const file = switch (level) {
.info, .debug => stdout_file,
.warn, .err => stderr_file,
};
var fmt_buffer = std.mem.zeroes([4096]u8);
var fmt_writer = std.Io.Writer.fixed(&fmt_buffer);
fmt_writer.print(format ++ "\n", args) catch {};
fmt_writer.flush() catch return;
var last_pos: usize = 0;
while (std.mem.indexOfScalarPos(u8, &fmt_buffer, last_pos, '\n')) |pos| {
var buffer = std.mem.zeroes([512]u8);
var out_config = std.Io.tty.Config.detect(file);
var writer = std.Io.Writer.fixed(&buffer);
out_config.setColor(&writer, .magenta) catch {};
writer.print("[StrollDriver ", .{}) catch {};
if (!builtin.is_test) {
out_config.setColor(&writer, .cyan) catch {};
writer.print(root.DRIVER_NAME, .{}) catch {};
}
out_config.setColor(&writer, .yellow) catch {};
writer.print(" {d:02}:{d:02}:{d:02}.{d:03}", .{ now.hour, now.minute, now.second, @divFloor(now.nanosecond, std.time.ns_per_ms) }) catch {};
out_config.setColor(&writer, .magenta) catch {};
writer.print("]", .{}) catch {};
out_config.setColor(&writer, level_color) catch {};
writer.print(prefix, .{}) catch {};
out_config.setColor(&writer, switch (level) {
.err => .red,
.warn => .magenta,
else => .green,
}) catch {};
writer.print("{s: >30}", .{scope_prefix}) catch {};
out_config.setColor(&writer, .reset) catch {};
if (getManager().get().indent_enabled) {
for (0..getManager().get().indent_level) |_| {
writer.print("> ", .{}) catch {};
}
}
writer.print("{s}\n", .{fmt_buffer[last_pos..pos]}) catch {};
writer.flush() catch return;
if (level == .debug and lib.getLogVerboseLevel() == .Standard) {
getManager().get().debug_stack.pushBack(.{
.log = buffer,
.indent_level = getManager().get().indent_level,
.log_level = level,
}) catch return;
return;
}
if (getManager().get().indent_enabled) {
while (getManager().get().debug_stack.len() != 0) {
const elem = getManager().get().debug_stack.popFront();
switch (elem.log_level) {
.info, .debug => _ = stdout_file.write(&elem.log) catch {},
.warn, .err => _ = stderr_file.write(&elem.log) catch {},
}
}
}
switch (level) {
.info, .debug => _ = stdout_file.write(&buffer) catch {},
.warn, .err => _ = stderr_file.write(&buffer) catch {},
}
last_pos = pos + 1;
}
}