From 82109c68ce9a1e13c3685d15e34fb9d91c869625 Mon Sep 17 00:00:00 2001 From: Lucas Santos Date: Sun, 19 Apr 2026 21:59:41 -0300 Subject: [PATCH 1/2] Replaces inline for loops with proper runtime loops. --- src/vulkan/render.zig | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/vulkan/render.zig b/src/vulkan/render.zig index 46ee002..746296b 100644 --- a/src/vulkan/render.zig +++ b/src/vulkan/render.zig @@ -1505,11 +1505,22 @@ const Renderer = struct { fn renderWrappers(self: *Self) !void { try self.writer.writeAll(command_flags_mixin); + try self.renderWrappersCommon(); try self.renderWrappersOfDispatchType(.base); try self.renderWrappersOfDispatchType(.instance); try self.renderWrappersOfDispatchType(.device); } + fn renderWrappersCommon(self: *Self) !void { + try self.writer.print( + \\fn loadCommonImpl(loader: *const fn(usize, [*:0]const u8) PfnVoidFunction, handle: usize, names: []const [*:0]const u8, ptrs: [*]PfnVoidFunction) void {{ + \\ for (ptrs[0..names.len], names) |*ptr, name| {{ + \\ ptr.* = loader(handle, name); + \\ }} + \\}} + , .{}); + } + fn renderWrappersOfDispatchType(self: *Self, dispatch_type: CommandDispatchType) !void { const name = dispatch_type.name(); @@ -1553,9 +1564,9 @@ const Renderer = struct { fn renderWrapperLoader(self: *Self, dispatch_type: CommandDispatchType) !void { const params = switch (dispatch_type) { - .base => "loader: anytype", - .instance => "instance: Instance, loader: anytype", - .device => "device: Device, loader: anytype", + .base => "loader: *const fn(Instance, [*:0]const u8) PfnVoidFunction", + .instance => "instance: Instance, loader: *const fn(Instance, [*:0]const u8) PfnVoidFunction", + .device => "device: Device, loader: *const fn(Device, [*:0]const u8) PfnVoidFunction", }; const loader_first_arg = switch (dispatch_type) { @@ -1569,11 +1580,13 @@ const Renderer = struct { try self.writer.print( \\pub fn load({[params]s}) Self {{ \\ var self: Self = .{{ .dispatch = .{{}} }}; - \\ inline for (std.meta.fields(Dispatch)) |field| {{ - \\ if (loader({[first_arg]s}, field.name.ptr)) |cmd_ptr| {{ - \\ @field(self.dispatch, field.name) = @ptrCast(cmd_ptr); - \\ }} - \\ }} + \\ const names = comptime blk:{{ + \\ const fields = @typeInfo(Dispatch).@"struct".fields; + \\ var names: [fields.len][*:0]const u8 = undefined; + \\ for (&names, fields) |*d, f| d.* = f.name.ptr; + \\ break :blk names; + \\ }}; + \\ loadCommonImpl(@ptrCast(loader), @intFromEnum({[first_arg]s}), &names, @ptrCast(&self.dispatch)); \\ return self; \\}} , .{ .params = params, .first_arg = loader_first_arg }); From a4ae68c3e4458c22055f8d9a8051e313d8755331 Mon Sep 17 00:00:00 2001 From: Lucas Santos Date: Mon, 20 Apr 2026 19:42:03 -0300 Subject: [PATCH 2/2] Makes wrapper an extern struct Also, change `loader` function back to being `anytype`, as a concrete type was causing problems related to callconv. --- src/vulkan/render.zig | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/src/vulkan/render.zig b/src/vulkan/render.zig index 746296b..9935c65 100644 --- a/src/vulkan/render.zig +++ b/src/vulkan/render.zig @@ -1479,7 +1479,7 @@ const Renderer = struct { fn renderDispatchTable(self: *Self, dispatch_type: CommandDispatchType) !void { try self.writer.print( - "pub const {s}Dispatch = struct {{\n", + "pub const {s}Dispatch = extern struct {{\n", .{dispatch_type.name()}, ); @@ -1505,29 +1505,18 @@ const Renderer = struct { fn renderWrappers(self: *Self) !void { try self.writer.writeAll(command_flags_mixin); - try self.renderWrappersCommon(); try self.renderWrappersOfDispatchType(.base); try self.renderWrappersOfDispatchType(.instance); try self.renderWrappersOfDispatchType(.device); } - fn renderWrappersCommon(self: *Self) !void { - try self.writer.print( - \\fn loadCommonImpl(loader: *const fn(usize, [*:0]const u8) PfnVoidFunction, handle: usize, names: []const [*:0]const u8, ptrs: [*]PfnVoidFunction) void {{ - \\ for (ptrs[0..names.len], names) |*ptr, name| {{ - \\ ptr.* = loader(handle, name); - \\ }} - \\}} - , .{}); - } - fn renderWrappersOfDispatchType(self: *Self, dispatch_type: CommandDispatchType) !void { const name = dispatch_type.name(); try self.writer.print( \\pub const {0s}Wrapper = {0s}WrapperWithCustomDispatch({0s}Dispatch); \\pub fn {0s}WrapperWithCustomDispatch(DispatchType: type) type {{ - \\ return struct {{ + \\ return extern struct {{ \\ const Self = @This(); \\ pub const Dispatch = DispatchType; \\ @@ -1564,9 +1553,9 @@ const Renderer = struct { fn renderWrapperLoader(self: *Self, dispatch_type: CommandDispatchType) !void { const params = switch (dispatch_type) { - .base => "loader: *const fn(Instance, [*:0]const u8) PfnVoidFunction", - .instance => "instance: Instance, loader: *const fn(Instance, [*:0]const u8) PfnVoidFunction", - .device => "device: Device, loader: *const fn(Device, [*:0]const u8) PfnVoidFunction", + .base => "loader: anytype", + .instance => "instance: Instance, loader: anytype", + .device => "device: Device, loader: anytype", }; const loader_first_arg = switch (dispatch_type) { @@ -1586,7 +1575,10 @@ const Renderer = struct { \\ for (&names, fields) |*d, f| d.* = f.name.ptr; \\ break :blk names; \\ }}; - \\ loadCommonImpl(@ptrCast(loader), @intFromEnum({[first_arg]s}), &names, @ptrCast(&self.dispatch)); + \\ const self_as_ptr: [*]?*const anyopaque = @ptrCast(&self.dispatch); + \\ for (self_as_ptr[0..names.len], names) |*ptr, name| {{ + \\ ptr.* = loader({[first_arg]s}, name); + \\ }} \\ return self; \\}} , .{ .params = params, .first_arg = loader_first_arg });