Skip to content

Commit

Permalink
[progress #146] custom bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
tiawl committed Mar 22, 2024
1 parent d3fedc0 commit faf3b99
Show file tree
Hide file tree
Showing 16 changed files with 1,051 additions and 841 deletions.
200 changes: 186 additions & 14 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ fn compile_shaders (builder: *std.Build, exe: *std.Build.Step.Compile, profile:
return try write_index (builder, &tree);
}

fn generate_prototypes (builder: *std.Build) ![] const u8
fn generate_literals_prototypes (builder: *std.Build) ![] const u8
{
builder.cache_root.handle.makeDir ("prototypes") catch |err|
{
Expand Down Expand Up @@ -419,42 +419,214 @@ fn link (builder: *std.Build, profile: *const Profile) !*std.Build.Module
return binding;
}

fn import (builder: *std.Build, exe: *std.Build.Step.Compile, profile: *const Profile) !void
fn import_glfw (builder: *std.Build, profile: *const Profile, c: *std.Build.Module) !*std.Build.Module
{
const datetime_dep = builder.dependency ("zig-datetime", .{
const path = try builder.build_root.join (builder.allocator, &.{ "src", "binding", "glfw", });

var modules = std.ArrayList (*std.Build.Module).init (builder.allocator);

var dir = try builder.build_root.handle.openDir (path, .{ .iterate = true, });
defer dir.close ();

var it = dir.iterate ();
while (try it.next ()) |entry|
{
switch (entry.kind)
{
.file => {
if (!std.mem.eql (u8, entry.name, "glfw.zig"))
{
try modules.append (builder.createModule (.{
.root_source_file = .{ .path = try std.fs.path.join (builder.allocator, &.{ path, entry.name, }), },
.target = profile.target,
.optimize = profile.optimize,
}));
modules.items [modules.items.len - 1].addImport ("c", c);
}
},
else => {},
}
}

const glfw = builder.createModule (.{
.root_source_file = .{ .path = try std.fs.path.join (builder.allocator, &.{ path, "glfw.zig", }), },
.target = profile.target,
.optimize = profile.optimize,
});
const datetime = datetime_dep.module ("zig-datetime");
glfw.addImport ("c", c);

const shader = builder.createModule (.{
.root_source_file = .{ .path = try compile_shaders (builder, exe, profile), },
for (modules.items) |module|
{
const name = std.fs.path.stem (std.fs.path.basename (module.root_source_file.?.getPath (builder)));
glfw.addImport (name, module);
module.addImport ("glfw", glfw);
for (modules.items) |other|
{
const other_name = std.fs.path.stem (std.fs.path.basename (other.root_source_file.?.getPath (builder)));
if (std.mem.eql (u8, name, other_name)) continue;
module.addImport (other_name, other);
}
}

return glfw;
}

fn import_vk (builder: *std.Build, profile: *const Profile, c: *std.Build.Module) !*std.Build.Module
{
const literals = builder.createModule (.{
.root_source_file = .{ .path = try generate_literals_prototypes (builder), },
.target = profile.target,
.optimize = profile.optimize,
});

const c = try link (builder, profile);
const path = try builder.build_root.join (builder.allocator, &.{ "src", "binding", "vk", });

const glfw = builder.createModule (.{
.root_source_file = .{ .path = try builder.build_root.join (builder.allocator, &.{ "src", "binding", "glfw", "glfw.zig", }), },
const raw = builder.createModule (.{
.root_source_file = .{ .path = try std.fs.path.join (builder.allocator, &.{ path, "raw.zig", }), },
.target = profile.target,
.optimize = profile.optimize,
});
glfw.addImport ("c", c);
raw.addImport ("c", c);
raw.addImport ("literals", literals);

var modules = std.ArrayList (*std.Build.Module).init (builder.allocator);

var dir = try builder.build_root.handle.openDir (path, .{ .iterate = true, });
defer dir.close ();

var it = dir.iterate ();
while (try it.next ()) |entry|
{
switch (entry.kind)
{
.file => {
if (!std.mem.eql (u8, entry.name, "vk.zig") and !std.mem.eql (u8, entry.name, "raw.zig") and
!std.mem.eql (u8, entry.name, "ext.zig") and !std.mem.eql (u8, entry.name, "khr.zig"))
{
try modules.append (builder.createModule (.{
.root_source_file = .{ .path = try std.fs.path.join (builder.allocator, &.{ path, entry.name, }), },
.target = profile.target,
.optimize = profile.optimize,
}));
modules.items [modules.items.len - 1].addImport ("c", c);
modules.items [modules.items.len - 1].addImport ("raw", raw);
}
},
else => {},
}
}

const ext = builder.createModule (.{
.root_source_file = .{ .path = try std.fs.path.join (builder.allocator, &.{ path, "ext.zig", }), },
.target = profile.target,
.optimize = profile.optimize,
});
ext.addImport ("c", c);
ext.addImport ("raw", raw);

var ext_subs = std.ArrayList (*std.Build.Module).init (builder.allocator);

const prototypes = builder.createModule (.{
.root_source_file = .{ .path = try generate_prototypes (builder), },
const ext_path = try std.fs.path.join (builder.allocator, &.{ path, "ext", });
var ext_dir = try builder.build_root.handle.openDir (ext_path, .{ .iterate = true, });
defer ext_dir.close ();

var walker = try ext_dir.walk (builder.allocator);
defer walker.deinit();

while (try walker.next ()) |entry|
{
switch (entry.kind)
{
.file => {
try ext_subs.append (builder.createModule (.{
.root_source_file = .{ .path = try std.fs.path.join (builder.allocator, &.{ ext_path, entry.path, }), },
.target = profile.target,
.optimize = profile.optimize,
}));
ext_subs.items [ext_subs.items.len - 1].addImport ("c", c);
ext_subs.items [ext_subs.items.len - 1].addImport ("raw", raw);
ext.addImport (std.fs.path.stem (entry.basename), ext_subs.items [ext_subs.items.len - 1]);
},
else => {},
}
}

try modules.append (ext);

const khr = builder.createModule (.{
.root_source_file = .{ .path = try std.fs.path.join (builder.allocator, &.{ path, "khr.zig", }), },
.target = profile.target,
.optimize = profile.optimize,
});
khr.addImport ("c", c);
khr.addImport ("raw", raw);

var khr_subs = std.ArrayList (*std.Build.Module).init (builder.allocator);

const khr_path = try std.fs.path.join (builder.allocator, &.{ path, "khr", });
var khr_dir = try builder.build_root.handle.openDir (khr_path, .{ .iterate = true, });
defer khr_dir.close ();

walker = try khr_dir.walk (builder.allocator);
defer walker.deinit();

while (try walker.next ()) |entry|
{
switch (entry.kind)
{
.file => {
try khr_subs.append (builder.createModule (.{
.root_source_file = .{ .path = try std.fs.path.join (builder.allocator, &.{ khr_path, entry.path, }), },
.target = profile.target,
.optimize = profile.optimize,
}));
khr_subs.items [khr_subs.items.len - 1].addImport ("c", c);
khr_subs.items [khr_subs.items.len - 1].addImport ("raw", raw);
khr.addImport (std.fs.path.stem (entry.basename), khr_subs.items [khr_subs.items.len - 1]);
},
else => {},
}
}

try modules.append (khr);

const vk = builder.createModule (.{
.root_source_file = .{ .path = try builder.build_root.join (builder.allocator, &.{ "src", "binding", "vk", "vk.zig", }), },
.root_source_file = .{ .path = try std.fs.path.join (builder.allocator, &.{ path, "vk.zig", }), },
.target = profile.target,
.optimize = profile.optimize,
});
vk.addImport ("c", c);
vk.addImport ("prototypes", prototypes);
vk.addImport ("raw", raw);
raw.addImport ("vk", vk);
for (modules.items) |module|
{
vk.addImport (std.fs.path.stem (std.fs.path.basename (module.root_source_file.?.getPath (builder))), module);
module.addImport ("vk", vk);
}
for (khr_subs.items) |khr_sub| khr_sub.addImport ("vk", vk);
for (ext_subs.items) |ext_sub| ext_sub.addImport ("vk", vk);

return vk;
}

fn import (builder: *std.Build, exe: *std.Build.Step.Compile, profile: *const Profile) !void
{
const datetime_dep = builder.dependency ("zig-datetime", .{
.target = profile.target,
.optimize = profile.optimize,
});
const datetime = datetime_dep.module ("zig-datetime");

const shader = builder.createModule (.{
.root_source_file = .{ .path = try compile_shaders (builder, exe, profile), },
.target = profile.target,
.optimize = profile.optimize,
});

const c = try link (builder, profile);

const glfw = try import_glfw (builder, profile, c);
const vk = try import_vk (builder, profile, c);

const imgui = builder.createModule (.{
.root_source_file = .{ .path = try builder.build_root.join (builder.allocator, &.{ "src", "binding", "imgui.zig", }), },
Expand Down
2 changes: 1 addition & 1 deletion src/binding/glfw/context.zig
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const c = @import ("c");
const std = @import ("std");

const glfw = @import ("glfw.zig");
const glfw = @import ("glfw");

pub const Context = struct
{
Expand Down
8 changes: 4 additions & 4 deletions src/binding/glfw/glfw.zig
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const c = @import ("c");

pub const Context = @import ("context.zig").Context;
pub const Error = @import ("error.zig").Error;
pub const vk = @import ("vk.zig").vk;
pub const Window = @import ("window.zig").Window;
pub const Context = @import ("context").Context;
pub const Error = @import ("error").Error;
pub const vk = @import ("vk").vk;
pub const Window = @import ("window").Window;

pub const Bool = enum (c_int)
{
Expand Down
2 changes: 1 addition & 1 deletion src/binding/glfw/window.zig
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const c = @import ("c");
const std = @import ("std");

const glfw = @import ("glfw.zig");
const glfw = @import ("glfw");

pub const Window = struct
{
Expand Down
97 changes: 97 additions & 0 deletions src/binding/vk/device.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
const std = @import ("std");
const c = @import ("c");

const vk = @import ("vk");
const raw = @import ("raw");

pub const Device = enum (usize)
{
NULL_HANDLE = 0, _,
pub const Memory = enum (u64) { NULL_HANDLE = 0, _, };
pub const Size = u64;

pub fn load (self: @This ()) !void
{
const loader: *const fn (vk.Device, [*:0] const u8) callconv (vk.call_conv) ?*const fn () callconv (vk.call_conv) void = @ptrCast (&raw.prototypes.instance.vkGetDeviceProcAddr);
inline for (std.meta.fields (@TypeOf (raw.prototypes.device))) |field|
{
const name: [*:0] const u8 = @ptrCast (field.name ++ "\x00");
const pointer = loader (self, name) orelse return error.CommandLoadFailure;
@field (raw.prototypes.device, field.name) = @ptrCast (pointer);
}
}

pub fn create (physical_device: vk.PhysicalDevice, p_create_info: *const vk.Device.Create.Info, p_allocator: ?*const vk.AllocationCallbacks) !vk.Device
{
var device: Device = undefined;
const result = raw.prototypes.instance.vkCreateDevice (physical_device, p_create_info, p_allocator, &device);
if (result > 0)
{
std.debug.print ("{s} failed with {} status code\n", .{ @typeName (@This ()) ++ "." ++ @src ().fn_name, result, });
return error.UnexpectedResult;
}
return device;
}

pub fn destroy (self: @This (), p_allocator: ?*const vk.AllocationCallbacks) void
{
raw.prototypes.device.vkDestroyDevice (self, p_allocator);
}

pub const Create = extern struct
{
pub const Flags = u32;
pub const Info = extern struct
{
s_type: vk.StructureType = .DEVICE_CREATE_INFO,
p_next: ?*const anyopaque = null,
flags: vk.Device.Create.Flags = 0,
queue_create_info_count: u32,
p_queue_create_infos: [*] const vk.Device.Queue.Create.Info,
enabled_layer_count: u32 = 0,
pp_enabled_layer_names: ?[*] const [*:0] const u8 = null,
enabled_extension_count: u32 = 0,
pp_enabled_extension_names: ?[*] const [*:0]const u8 = null,
p_enabled_features: ?*const vk.PhysicalDevice.Features = null,
};
};

pub const ExtensionProperties = extern struct
{
pub fn enumerate (physical_device: vk.PhysicalDevice, p_layer_name: ?[*:0] const u8, p_property_count: *u32, p_properties: ?[*] vk.ExtensionProperties) !void
{
const result = raw.prototypes.structless.vkEnumerateDeviceExtensionProperties (physical_device, p_layer_name, p_property_count, p_properties);
if (result > 0)
{
std.debug.print ("{s} failed with {} status code\n", .{ @typeName (@This ()) ++ "." ++ @src ().fn_name, result, });
return error.UnexpectedResult;
}
}
};

pub const Queue = extern struct
{
pub fn get (device: vk.Device, queue_family_index: u32, queue_index: u32) vk.Queue
{
var queue: vk.Queue = undefined;
raw.prototypes.device.vkGetDeviceQueue (device, queue_family_index, queue_index, &queue);
return queue;
}

pub const Create = extern struct
{
pub const Flags = u32;

pub const Info = extern struct
{
s_type: vk.StructureType = .DEVICE_QUEUE_CREATE_INFO,
p_next: ?*const anyopaque = null,
flags: vk.Device.Queue.Create.Flags = 0,
queue_family_index: u32,
queue_count: u32,
p_queue_priorities: [*] const f32,
};
};
};
};

Loading

0 comments on commit faf3b99

Please sign in to comment.