From 3ddb09068a5c82371bc6dbd6f0e7f0912997f978 Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Sat, 25 Oct 2025 01:48:42 +0200 Subject: [PATCH] dinishing bindings, adding some tess --- build.zig | 90 ++++++++++++++++---------------- build.zig.zon | 5 +- src/BackendParameters.zig | 65 +++++++++++++++++------ src/FilesystemModuleResolver.zig | 23 +++++++- src/GlslWriter.zig | 20 ++++--- src/lib.zig | 16 ++++++ 6 files changed, 149 insertions(+), 70 deletions(-) diff --git a/build.zig b/build.zig index 51243d1..0d349d0 100644 --- a/build.zig +++ b/build.zig @@ -5,26 +5,14 @@ const Step = std.Build.Step; pub const Libsource = enum { source, prebuild }; -// based on ziglua's build.zig - -// Although this function looks imperative, note that its job is to -// declaratively construct a build graph that will be executed by an external -// runner. -pub fn build(b: *Build) void { - // Remove the default install and uninstall steps +pub fn build(b: *Build) !void { b.top_level_steps = .{}; const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); - const libsource = b.option(Libsource, "libsource", "Use prebuild or compile from sources") orelse .source; const shared = b.option(bool, "shared", "Build shared library instead of static") orelse false; - if (libsource == .prebuild) { - std.debug.panic("Prebuild aren't available for now", .{}); - } - - // Zig module const nzigsl = b.addModule("nzigsl", .{ .target = target, .optimize = optimize, @@ -37,34 +25,34 @@ pub fn build(b: *Build) void { .linkage = .static, }); - // Expose build configuration to the nzigsl module + const mod_tests = b.addTest(.{ + .root_module = nzigsl, + }); + const config = b.addOptions(); - config.addOption(Libsource, "libsource", libsource); nzigsl.addOptions("config", config); nzsldep: { - const upstream = b.lazyDependency(if (libsource == .source) "nzsl" else break :nzsldep, .{}) orelse break :nzsldep; + const upstream = b.lazyDependency("nzsl", .{}) orelse break :nzsldep; const nazaraUtils = b.lazyDependency("NazaraUtils", .{}) orelse break :nzsldep; const frozen = b.lazyDependency("frozen", .{}) orelse break :nzsldep; const fmt = b.lazyDependency("fmt", .{}) orelse break :nzsldep; const ordered_map = b.lazyDependency("ordered_map", .{}) orelse break :nzsldep; const fast_float = b.lazyDependency("fast_float", .{}) orelse break :nzsldep; + const lz4 = b.lazyDependency("lz4", .{}) orelse break :nzsldep; - const lib = switch (libsource) { - .source => buildNzsl(b, target, optimize, upstream, nazaraUtils, frozen, fmt, ordered_map, fast_float, shared), - else => unreachable, - }; + const lib = try buildNzsl(b, target, optimize, upstream, nazaraUtils, frozen, fmt, ordered_map, fast_float, lz4, shared); - // Expose the Nzsl artifact b.installArtifact(lib); - //nzigsl.addSystemIncludePath(upstream.path("include")); - nzigsl.linkLibrary(lib); docs.linkLibrary(lib); } - // Examples + const run_tests = b.addRunArtifact(mod_tests); + const test_step = b.step("test", "Run tests"); + test_step.dependOn(&run_tests.step); + const examples = [_]struct { []const u8, []const u8 }{ .{ "mandelbrot", "examples/mandelbrot.zig" }, }; @@ -105,12 +93,25 @@ pub fn build(b: *Build) void { docs_step.dependOn(&install_docs.step); } -fn buildNzsl(b: *Build, target: Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, upstream: *Build.Dependency, nazaraUtils: *Build.Dependency, frozen: *Build.Dependency, ordered_map: *Build.Dependency, fast_float: *Build.Dependency, fmt: *Build.Dependency, shared: bool) *Step.Compile { +fn buildNzsl( + b: *Build, + target: Build.ResolvedTarget, + optimize: std.builtin.OptimizeMode, + upstream: *Build.Dependency, + nazaraUtils: *Build.Dependency, + frozen: *Build.Dependency, + fmt: *Build.Dependency, + ordered_map: *Build.Dependency, + fast_float: *Build.Dependency, + lz4: *Build.Dependency, + shared: bool, +) !*Step.Compile { const lib = b.addLibrary(.{ .name = "nzsl", .root_module = b.createModule(.{ .target = target, .optimize = optimize, + .link_libcpp = true, }), .linkage = if (shared) .dynamic else .static, }); @@ -123,41 +124,32 @@ fn buildNzsl(b: *Build, target: Build.ResolvedTarget, optimize: std.builtin.Opti lib.addSystemIncludePath(fmt.path("include")); lib.addSystemIncludePath(ordered_map.path("include")); lib.addSystemIncludePath(fast_float.path("include")); + lib.addSystemIncludePath(lz4.path("include")); const flags = [_][]const u8{ - if (shared) - "-DCNZSL_DYNAMIC" - else - "-DCNZSL_STATIC", if (shared) "-DNZSL_DYNAMIC" else "-DNZSL_STATIC", + if (shared) "-DCNZSL_DYNAMIC" else "-DCNZSL_STATIC", "-DCNZSL_BUILD", "-DNZSL_BUILD", "-DFMT_HEADER_ONLY", - - // Define target-specific macro - //switch (target.result.os.tag) { - //.linux => "-DLUA_USE_LINUX", - //.macos => "-DLUA_USE_MACOSX", - //.windows => "-DLUA_USE_WINDOWS", - //else => "-DLUA_USE_POSIX", - //}, - - // Enable api check - // if (optimize == .Debug) "-DLUA_USE_APICHECK" else "", }; - const nzsl_source_files = &nzsl_source_files_list; - lib.addCSourceFiles(.{ .root = .{ .dependency = .{ .dependency = upstream, .sub_path = "", } }, - .files = nzsl_source_files, + .files = &nzsl_source_files, .flags = &flags, }); - lib.linkLibCpp(); + lib.addCSourceFiles(.{ + .root = .{ .dependency = .{ + .dependency = lz4, + .sub_path = "lib", + } }, + .files = &lz4_source_files, + }); lib.installHeader(upstream.path("include/CNZSL/SpirvWriter.h"), "CNZSL/SpirvWriter.h"); lib.installHeader(upstream.path("include/CNZSL/ShaderStageType.h"), "CNZSL/ShaderStageType.h"); @@ -175,7 +167,7 @@ fn buildNzsl(b: *Build, target: Build.ResolvedTarget, optimize: std.builtin.Opti return lib; } -const nzsl_source_files_list = [_][]const u8{ +const nzsl_source_files = [_][]const u8{ "src/NZSL/SpirvWriter.cpp", "src/NZSL/SpirV/SpirvSectionBase.cpp", "src/NZSL/SpirV/SpirvPrinter.cpp", @@ -239,3 +231,11 @@ const nzsl_source_files_list = [_][]const u8{ "src/CNZSL/FilesystemModuleResolver.cpp", "src/CNZSL/BackendParameters.cpp", }; + +const lz4_source_files = [_][]const u8{ + "lz4.c", + "lz4hc.c", + "lz4frame.c", + "xxhash.c", + "lz4file.c", +}; diff --git a/build.zig.zon b/build.zig.zon index e5ab531..ff1928f 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -8,7 +8,6 @@ .url = "git+https://github.com/NazaraEngine/ShaderLang?ref=v1.1.1#6d06572eaa664b1655f57522edf1e8c88292be0a", .hash = "N-V-__8AAPOQIwAwA5SQCrbVxrBp5Q7YX--899XJIjFv6rZn", .lazy = true, - .lazy = true, }, .NazaraUtils = .{ .url = "git+https://github.com/NazaraEngine/NazaraUtils?ref=v1.0.0#d2f5d902ed9ac2bc8e26a015b1ff02edc5e3b550", @@ -35,6 +34,10 @@ .hash = "N-V-__8AABEwCAAXomDLtLslEEK5zzy4Yy0b2RC-WS-DgdnU", .lazy = true, }, + .lz4 = .{ + .url = "git+https://github.com/lz4/lz4?ref=v1.10.0#ebb370ca83af193212df4dcbadcc5d87bc0de2f0", + .hash = "N-V-__8AAJqFGQCAYVWzZWCL3-wqB2UCxRqBJ68dgAtVEtPu", + }, }, .paths = .{ "", diff --git a/src/BackendParameters.zig b/src/BackendParameters.zig index 40707ee..90aa794 100644 --- a/src/BackendParameters.zig +++ b/src/BackendParameters.zig @@ -1,6 +1,7 @@ const std = @import("std"); const DebugLevel = @import("lib.zig").DebugLevel; const OptionHash = @import("lib.zig").OptionHash; +const FilesystemModuleResolver = @import("lib.zig").FilesystemModuleResolver; const cnzsl = @cImport({ @cInclude("CNZSL/CNZSL.h"); }); @@ -21,37 +22,38 @@ pub fn deinit(self: Self) void { } pub fn enableDeadCodeRemoval(self: Self, enable: bool) void { - cnzsl.nzslBackendParametersEnableDeadCodeRemoval(self.instance, enable); + cnzsl.nzslBackendParametersEnableDeadCodeRemoval(self.instance, @intFromBool(enable)); } pub fn enableOptimization(self: Self, enable: bool) void { - cnzsl.nzslBackendParametersEnableOptimization(self.instance, enable); + cnzsl.nzslBackendParametersEnableOptimization(self.instance, @intFromBool(enable)); } pub fn enableResolving(self: Self, enable: bool) void { - cnzsl.nzslBackendParametersEnableResolving(self.instance, enable); + cnzsl.nzslBackendParametersEnableResolving(self.instance, @intFromBool(enable)); } pub fn enableTargetRequired(self: Self, enable: bool) void { - cnzsl.nzslBackendParametersEnableTargetRequired(self.instance, enable); + cnzsl.nzslBackendParametersEnableTargetRequired(self.instance, @intFromBool(enable)); } pub fn enableValidation(self: Self, enable: bool) void { - cnzsl.nzslBackendParametersEnableValidation(self.instance, enable); + cnzsl.nzslBackendParametersEnableValidation(self.instance, @intFromBool(enable)); } pub fn setDebugLevel(self: Self, debug_level: DebugLevel) void { cnzsl.nzslBackendParametersSetDebugLevel(self.instance, @intFromEnum(debug_level)); } -//pub fn SetModuleResolver_Filesystem(self: Self, const nzslFilesystemModuleResolver* resolverPtr) void { -//} +pub fn SetModuleResolverFilesystem(self: Self, filesystem_module_resolver: FilesystemModuleResolver) void { + cnzsl.nzslBackendParametersSetModuleResolver_Filesystem(@ptrCast(self.instance), @ptrCast(filesystem_module_resolver.instance)); +} -pub fn setOption(self: Self, hash: OptionHash, value: anytype) void { +pub fn setOption(self: Self, hash: OptionHash, value: anytype) !void { const T = @TypeOf(value); switch (@typeInfo(T)) { - .vector => |v| self.setOption(hash, @as([v.len]v.child, value)), - .float, .int, .comptime_float, .comptime_int, .bool => self.setOption(hash, [1]T{value}), + .vector => |v| try self.setOption(hash, @as([v.len]v.child, value)), + .float, .int, .comptime_float, .comptime_int, .bool => try self.setOption(hash, [1]T{value}), .array => |a| { const sanitized_value, const sanitized_primitive_name = switch (@typeInfo(a.child)) { .bool => blk: { @@ -61,21 +63,52 @@ pub fn setOption(self: Self, hash: OptionHash, value: anytype) void { } break :blk .{ new_array, "bool" }; }, - .float => |f| if (f.bits != 32) @compileError("Unhandled float size (not 32 bits)") else .{ value, @typeName(a.child) }, - .int => |i| if (i.bits != 32) @compileError("Unhandled integer size (not 32 bits)") else .{ value, @typeName(a.child) }, + .float => |f| if (f.bits == 32) .{ value, @typeName(a.child) } else return error.Not32BitsFloat, + .int => |i| if (i.bits == 32) .{ value, @typeName(a.child) } else return error.Not32BitsInt, .comptime_float => .{ value, "f32" }, .comptime_int => .{ value, "i32" }, - else => @compileError("Unhandled type"), + else => return error.UnhandledType, }; const type_name, const c_value = switch (a.len) { 1 => .{ "" ++ sanitized_primitive_name, sanitized_value[0] }, - 2...4 => .{ "vec" ++ [_]u8{'0' + a.len} ++ sanitized_primitive_name, @as([*c]const a.child, @ptrCast(&sanitized_value)) }, - else => @compileError("Unhandled array or vector size"), + 2...4 => .{ "vec" ++ [_]u8{'0' + a.len} ++ sanitized_primitive_name, @as([*c]const @TypeOf(sanitized_value[0]), @ptrCast(&sanitized_value)) }, + else => return error.UnhandledArrayOrVectorSize, }; @call(.auto, @field(cnzsl, "nzslBackendParametersSetOption_" ++ type_name), .{ self.instance, hash, c_value }); }, - else => @compileError("Unhandled type"), + else => return error.UnhandledType, + } +} + +test "init" { + const params = try init(); + defer params.deinit(); +} + +test "valid setOption" { + const params = try init(); + defer params.deinit(); + + const primitive_types = [_]type{ + f32, + i32, + u32, + bool, + }; + + inline for (1..4) |i| { + inline for (primitive_types) |T| { + const value: T = undefined; + if (i == 1) { + try params.setOption(0, value); + } else { + const array = [_]T{value} ** i; + const vector: @Vector(i, T) = array; + try params.setOption(0, vector); + try params.setOption(0, array); + } + } } } diff --git a/src/FilesystemModuleResolver.zig b/src/FilesystemModuleResolver.zig index 7fddb42..5f61774 100644 --- a/src/FilesystemModuleResolver.zig +++ b/src/FilesystemModuleResolver.zig @@ -9,7 +9,7 @@ const Self = @This(); instance: *cnzsl.nzslFilesystemModuleResolver, pub fn init() !Self { - const cfmr = cnzsl.nzslFilesystemModuleResolverCreate() orelse error.NullPointer; + const cfmr = cnzsl.nzslFilesystemModuleResolverCreate() orelse return error.NullPointer; return .{ .instance = cfmr, }; @@ -18,3 +18,24 @@ pub fn init() !Self { pub fn deinit(self: Self) void { cnzsl.nzslFilesystemModuleResolverDestroy(@ptrCast(self.instance)); } + +pub fn getLastError(self: Self) ![]const u8 { + const err = cnzsl.nzslFilesystemModuleResolverGetLastError(self.instance) orelse return error.NullPointer; + return std.mem.span(err); +} + +pub fn registerDirectory(self: Self, source_path: []const u8) void { + cnzsl.nzslFilesystemModuleResolverRegisterDirectory(@ptrCast(self.instance), source_path.ptr, source_path.len); +} + +pub fn registerFile(self: Self, source_path: []const u8) void { + cnzsl.nzslFilesystemModuleResolverRegisterFile(@ptrCast(self.instance), source_path.ptr, source_path.len); +} + +pub fn registerModule(self: Self, module: Module) void { + cnzsl.nzslFilesystemModuleResolverRegisterModule(@ptrCast(self.instance), @ptrCast(module.instance)); +} + +pub fn registerModuleFromSource(self: Self, source: []const u8) void { + cnzsl.nzslFilesystemModuleResolverRegisterModuleFromSource(@ptrCast(self.instance), source.ptr, source.len); +} diff --git a/src/GlslWriter.zig b/src/GlslWriter.zig index c530ee6..f0e9dbf 100644 --- a/src/GlslWriter.zig +++ b/src/GlslWriter.zig @@ -80,25 +80,31 @@ pub const Output = struct { return code[0..size]; } - pub fn getExplicitTextureBinding(self: InnerSelf, binding_name: [:0]const u8) i32 { + pub fn getExplicitTextureBinding(self: InnerSelf, binding_name: [:0]const u8) !i32 { const res = cnzsl.nzslGlslOutputGetExplicitTextureBinding(self.instance, binding_name); - return if (res != -1) res else error.BindingNameNotFound; + if (res == -1) { + return error.BindingNameNotFound; + } + return res; } - pub fn getExplicitUniformBlockBinding(self: InnerSelf, binding_name: [:0]const u8) i32 { + pub fn getExplicitUniformBlockBinding(self: InnerSelf, binding_name: [:0]const u8) !i32 { const res = cnzsl.nzslGlslOutputGetExplicitUniformBlockBinding(self.instance, binding_name); - return if (res != -1) res else error.BindingNameNotFound; + if (res == -1) { + return error.BindingNameNotFound; + } + return res; } pub fn usesDrawParameterBaseInstanceUniform(self: InnerSelf) bool { - return cnzsl.nzslGlslOutputGetUsesDrawParameterBaseInstanceUniform(self.instance); + return cnzsl.nzslGlslOutputGetUsesDrawParameterBaseInstanceUniform(self.instance) != 0; } pub fn usesDrawParameterBaseVertexUniform(self: InnerSelf) bool { - return cnzsl.nzslGlslOutputGetUsesDrawParameterBaseVertexUniform(self.instance); + return cnzsl.nzslGlslOutputGetUsesDrawParameterBaseVertexUniform(self.instance) != 0; } pub fn usesDrawParameterDrawIndexUniform(self: InnerSelf) bool { - return cnzsl.nzslGlslOutputGetUsesDrawParameterDrawIndexUniform(self.instance); + return cnzsl.nzslGlslOutputGetUsesDrawParameterDrawIndexUniform(self.instance) != 0; } }; diff --git a/src/lib.zig b/src/lib.zig index 0864af5..a8e2df7 100644 --- a/src/lib.zig +++ b/src/lib.zig @@ -31,3 +31,19 @@ pub const Module = @import("Module.zig"); pub const parser = @import("parser.zig"); pub const Serializer = @import("Serializer.zig"); pub const SpirvWriter = @import("SpirvWriter.zig"); + +test { + std.testing.refAllDeclsRecursive(@This()); +} + +test "hashOption" { + try std.testing.expect(try hashOption("test") == 2949673445); + try std.testing.expect(try hashOption("nzsl") == 1968067102); + try std.testing.expect(try hashOption("shaderlang") == 1855243988); + try std.testing.expect(try hashOption("a") == 3826002220); + try std.testing.expect(try hashOption("aa") == 1277494327); + try std.testing.expect(try hashOption("aaa") == 876991330); + try std.testing.expect(try hashOption("aaaa") == 1290481081); + try std.testing.expect(try hashOption("aaaaa") == 3996723976); + try std.testing.expect(try hashOption("aaaaaa") == 1828673099); +}