From e9f286a5d49d855ebb5f23c40eed8d38c7372e2a Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sat, 4 Jul 2020 03:00:54 +0200 Subject: [PATCH] Vulkan generate step --- build.zig | 73 ++++++++++++++++++++------ generator/vulkan/build-integration.zig | 43 +++++++++++++++ 2 files changed, 100 insertions(+), 16 deletions(-) create mode 100644 generator/vulkan/build-integration.zig diff --git a/build.zig b/build.zig index 146cc82..783804a 100644 --- a/build.zig +++ b/build.zig @@ -1,26 +1,67 @@ const std = @import("std"); const vkgen = @import("generator/index.zig"); const Builder = std.build.Builder; -const FmtStep = std.build.FmtStep; +const path = std.fs.path; -pub fn generateVk(b: *Builder) []const u8 { - const spec = std.fs.cwd().readFileAlloc(b.allocator, "examples/vk.xml", std.math.maxInt(usize)) catch unreachable; - const output = std.fs.path.join( - b.allocator, - &[_][]const u8{b.cache_root, "vk.zig"}, - ) catch unreachable; +const Resources = struct { + builder: *Builder, + wfs: *std.build.WriteFileStep, + data: std.ArrayList(u8), - const output_file = std.fs.cwd().createFile(output, .{}) catch unreachable; - defer output_file.close(); - vkgen.generateVk(b.allocator, spec, output_file.writer()) catch unreachable; + fn init(builder: *Builder) *Resources { + const res = builder.allocator.create(Resources) catch unreachable; + res.* = .{ + .builder = builder, + .wfs = builder.addWriteFiles(), + .data = std.ArrayList(u8).init(builder.allocator), + }; + return res; + } - return output; -} + fn addShader(self: *Resources, shader: []const u8) void { + const spv_name = std.mem.join( + self.builder.allocator, + "", + &[_][]const u8{shader, ".spv"}, + ) catch unreachable; + const dst = path.join( + self.builder.allocator, + &[_][]const u8{self.builder.cache_root, "test.frag.spv"} + ) catch unreachable; + + const src = path.join( + self.builder.allocator, + &[_][]const u8{self.builder.build_root, shader} + ) catch unreachable; + + const compile_step = self.builder.addSystemCommand(&[_][]const u8{ + "glslc", + "--target-env=vulkan1.2", + src, + "-o", + dst + }); + + self.wfs.step.dependOn(&compile_step.step); + + const writer = self.data.writer(); + writer.print("const @\"{}\" = @embedFile(\"{}\");", .{src, dst}) catch unreachable; + } + + fn finalize(self: *Resources) *std.build.WriteFileStep { + self.wfs.add("resources.zig", self.data.toOwnedSlice()); + return self.wfs; + } +}; pub fn build(b: *Builder) void { var test_step = b.step("test", "Run all the tests"); test_step.dependOn(&b.addTest("generator/index.zig").step); + const res = Resources.init(b); + res.addShader("examples/shaders/test.frag"); + const wfs = res.finalize(); + const target = b.standardTargetOptions(.{}); const mode = b.standardReleaseOptions(); const example_exe = b.addExecutable("example", "examples/main.zig"); @@ -29,11 +70,11 @@ pub fn build(b: *Builder) void { example_exe.install(); example_exe.linkSystemLibrary("c"); example_exe.linkSystemLibrary("glfw"); + example_exe.step.dependOn(&wfs.step); - const vk_path = generateVk(b); - const fmt_step = b.addFmt(&[_][]const u8{vk_path}); - example_exe.step.dependOn(&fmt_step.step); - example_exe.addPackagePath("vulkan", vk_path); + const gen_step = vkgen.VkGenerateStep.init(b, "examples/vk.xml", "vk.zig"); + example_exe.step.dependOn(&gen_step.step); + example_exe.addPackagePath("vulkan", gen_step.full_out_path); const example_run_cmd = example_exe.run(); example_run_cmd.step.dependOn(b.getInstallStep()); diff --git a/generator/vulkan/build-integration.zig b/generator/vulkan/build-integration.zig new file mode 100644 index 0000000..ce3c36a --- /dev/null +++ b/generator/vulkan/build-integration.zig @@ -0,0 +1,43 @@ +const std = @import("std"); +const generate = @import("generator.zig").generate; +const path = std.fs.path; +const Builder = std.build.Builder; +const Step = std.build.Step; + +pub const GenerateStep = struct { + step: Step, + builder: *Builder, + spec_path: []const u8, + full_out_path: []const u8, + + // relative_out_path is relative to builder.cache_root + pub fn init(builder: *Builder, spec_path: []const u8, relative_out_path: []const u8) *GenerateStep { + const self = builder.allocator.create(GenerateStep) catch unreachable; + self.* = .{ + .step = Step.init(.Custom, "vulkan-generate", builder.allocator, make), + .builder = builder, + .spec_path = spec_path, + .full_out_path = path.join(builder.allocator, &[_][]const u8{ + builder.cache_root, + relative_out_path, + }) catch unreachable, + }; + return self; + } + + fn make(step: *Step) !void { + const self = @fieldParentPtr(GenerateStep, "step", step); + const cwd = std.fs.cwd(); + + var out_buffer = std.ArrayList(u8).init(self.builder.allocator); + const spec = try std.fs.cwd().readFileAlloc(self.builder.allocator, self.spec_path, std.math.maxInt(usize)); + try generate(self.builder.allocator, spec, out_buffer.writer()); + + const tree = try std.zig.parse(self.builder.allocator, out_buffer.items); + + const dir = path.dirname(self.full_out_path).?; + try std.fs.cwd().makePath(dir); + const output_file = std.fs.cwd().createFile(self.full_out_path, .{}) catch unreachable; + _ = try std.zig.render(self.builder.allocator, output_file.outStream(), tree); + } +};