Integrate update shader compilation step to building
continuous-integration/drone/push Build is passing Details

This commit is contained in:
kayomn 2024-07-06 17:42:59 +01:00
parent e17d2b74ca
commit 640a06c86b
3 changed files with 160 additions and 73 deletions

View File

@ -1,29 +0,0 @@
#!/bin/python
import sys
import base64
import struct
def format_base64_to_u32(base64_string):
# Decode the Base64 string
decoded_bytes = base64.b64decode(base64_string)
# Interpret the bytes as a sequence of u32 values
u32_values = struct.unpack('I' * (len(decoded_bytes) // 4), decoded_bytes)
# Format the u32 values as C-style hex values
formatted_u32_values = ', '.join(f'0x{value:08x}' for value in u32_values)
# Split the formatted string into lines of 8 values each
lines = [', '.join(formatted_u32_values.split(', ')[i:i+8]) for i in range(0, len(u32_values), 8)]
# Print the formatted values
print(',\n'.join(lines))
if __name__ == "__main__":
if len(sys.argv) != 2:
print(f"Usage: python {sys.argv[0]} <base64_string>")
sys.exit(1)
base64_string = sys.argv[1]
format_base64_to_u32(base64_string)

203
build.zig
View File

@ -2,6 +2,17 @@ const builtin = @import("builtin");
const std = @import("std");
const SubPath = struct {
buffer: [max]u8 = [_]u8{0} ** max,
unused: u8 = max,
const max = 255;
pub fn utf8(self: *const SubPath) [:0]const u8 {
return self.buffer[0 .. (max - self.unused):0];
}
};
pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
@ -48,16 +59,52 @@ pub fn build(b: *std.Build) !void {
});
ona_module.addIncludePath(b.path("ext/"));
ona_module.linkLibrary(build_spirvcross(b, target, optimize));
b.step("test", "Run unit tests").dependOn(create: {
ona_module.linkLibrary(spirv_cross: {
const dir = "ext/spirv-cross/";
const sources = [_][]const u8{
"spirv_cross.cpp",
"spirv_parser.cpp",
"spirv_cross_parsed_ir.cpp",
"spirv_cfg.cpp",
"spirv_glsl.cpp",
"spirv_msl.cpp",
"spirv_hlsl.cpp",
"spirv_reflect.cpp",
"spirv_cross_util.cpp",
"spirv_cross_c.cpp",
};
const lib = b.addStaticLibrary(.{
.name = "spirvcross",
.target = target,
.optimize = optimize,
});
switch (lib.rootModuleTarget().abi) {
.msvc => lib.linkLibC(),
else => lib.linkLibCpp(),
}
inline for (sources) |src| {
lib.addCSourceFile(.{
.file = b.path(dir ++ src),
.flags = &.{"-fstrict-aliasing", "-DSPIRV_CROSS_C_API_GLSL", "-DSPIRV_CROSS_C_API_HLSL", "-DSPIRV_CROSS_C_API_MSL"},
});
}
break: spirv_cross lib;
});
b.step("test", "Run unit tests").dependOn(tests: {
const tests = b.addTest(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
break: create &tests.step;
break: tests &tests.step;
});
b.installArtifact(add: {
@ -73,47 +120,115 @@ pub fn build(b: *std.Build) !void {
exe.linkLibC();
exe.linkSystemLibrary("SDL2");
const shaders_sub_path = "src/ona/gfx/shaders/";
var shaders_dir = try std.fs.cwd().openDir(shaders_sub_path, .{
.iterate = true,
});
defer shaders_dir.close();
var shaders_walker = try shaders_dir.walk(b.allocator);
defer shaders_walker.deinit();
const Shader = struct {
source_sub_path: SubPath = .{},
binary_sub_path: SubPath = .{},
};
var pending_shaders = std.ArrayList(Shader).init(b.allocator);
defer pending_shaders.deinit();
scan_shaders: while (try shaders_walker.next()) |entry| {
if (entry.kind != .file) {
continue: scan_shaders;
}
const is_shader_file = std.mem.endsWith(u8, entry.path, ".frag") or std.mem.endsWith(u8, entry.path, ".vert");
if (!is_shader_file) {
continue: scan_shaders;
}
const shader_name = std.fs.path.stem(entry.path);
for (pending_shaders.items) |pending_shader| {
if (std.mem.endsWith(u8, pending_shader.source_sub_path.utf8(), shader_name)) {
continue: scan_shaders;
}
}
var shader = Shader{};
const source_sub_path = try std.fmt.bufPrint(&shader.source_sub_path.buffer, "{s}{s}", .{shaders_sub_path, shader_name});
const binary_sub_path = try std.fmt.bufPrint(&shader.binary_sub_path.buffer, "{s}.spv", .{source_sub_path});
shaders_dir.access(std.fs.path.basename(binary_sub_path), .{.mode = .read_only}) catch {
shader.source_sub_path.unused -= @intCast(source_sub_path.len);
shader.binary_sub_path.unused -= @intCast(binary_sub_path.len);
try pending_shaders.append(shader);
continue: scan_shaders;
};
if ((try shaders_dir.statFile(entry.basename)).mtime > (try shaders_dir.statFile(std.fs.path.basename(binary_sub_path))).mtime) {
shader.source_sub_path.unused -= @intCast(source_sub_path.len);
shader.binary_sub_path.unused -= @intCast(binary_sub_path.len);
try pending_shaders.append(shader);
continue: scan_shaders;
}
}
for (pending_shaders.items) |pending_shader| {
var vertex_binary_sub_path = SubPath{};
var fragment_binary_sub_path = SubPath{};
const source_sub_path_utf8 = pending_shader.source_sub_path.utf8();
vertex_binary_sub_path.unused -= @intCast((try std.fmt.bufPrint(&vertex_binary_sub_path.buffer, "{s}.vert.spv", .{source_sub_path_utf8})).len);
fragment_binary_sub_path.unused -= @intCast((try std.fmt.bufPrint(&fragment_binary_sub_path.buffer, "{s}.frag.spv", .{source_sub_path_utf8})).len);
const vertex_binary_sub_path_utf8 = vertex_binary_sub_path.utf8();
const fragment_binary_sub_path_utf8 = fragment_binary_sub_path.utf8();
const link_command = b.addSystemCommand(&.{
"spirv-link",
vertex_binary_sub_path_utf8,
fragment_binary_sub_path_utf8,
"-o",
pending_shader.binary_sub_path.utf8(),
});
exe.step.dependOn(&link_command.step);
link_command.step.dependOn(compile_vertex: {
const compile_command = b.addSystemCommand(&.{
"glslangValidator",
"-V",
vertex_binary_sub_path_utf8[0 .. vertex_binary_sub_path_utf8.len - 4],
"-o",
vertex_binary_sub_path_utf8,
});
break: compile_vertex &compile_command.step;
});
link_command.step.dependOn(compile_fragment: {
const compile_command = b.addSystemCommand(&.{
"glslangValidator",
"-V",
fragment_binary_sub_path_utf8[0 .. fragment_binary_sub_path_utf8.len - 4],
"-o",
fragment_binary_sub_path_utf8,
});
break: compile_fragment &compile_command.step;
});
}
break: add exe;
});
}
fn build_spirvcross(
b: *std.Build,
target: std.Build.ResolvedTarget,
mode: std.builtin.OptimizeMode,
) *std.Build.Step.Compile {
const dir = "ext/spirv-cross/";
const sources = [_][]const u8{
"spirv_cross.cpp",
"spirv_parser.cpp",
"spirv_cross_parsed_ir.cpp",
"spirv_cfg.cpp",
"spirv_glsl.cpp",
"spirv_msl.cpp",
"spirv_hlsl.cpp",
"spirv_reflect.cpp",
"spirv_cross_util.cpp",
"spirv_cross_c.cpp",
};
const lib = b.addStaticLibrary(.{
.name = "spirvcross",
.target = target,
.optimize = mode,
});
switch (lib.rootModuleTarget().abi) {
.msvc => lib.linkLibC(),
else => lib.linkLibCpp(),
}
inline for (sources) |src| {
lib.addCSourceFile(.{
.file = b.path(dir ++ src),
.flags = &.{"-fstrict-aliasing", "-DSPIRV_CROSS_C_API_GLSL", "-DSPIRV_CROSS_C_API_HLSL", "-DSPIRV_CROSS_C_API_MSL"},
});
}
return lib;
}

View File

@ -33,6 +33,7 @@ Ona is also the Catalan word for "wave".
Ona currently depends the following third-party tools to build it:
* Platform support for SDL2 at version 2.0.20 or above.
* SPIR-V shader compilation system utilities, namely `glslangValidator` and `spirv-link`.
* Zig compiler toolchain.
As the project evolves, dependencies on libraries external to the project codebase will be minimized or removed outright to meet the goals of the project as closely as possible.