From 0f35c35fd1036d25992edc31a55261a650b2b66f Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Sun, 18 Jan 2026 23:17:26 +0100 Subject: [PATCH] ye --- example/main.zig | 8 ++- example/shader.nzsl | 27 +++++--- example/shader.spv | Bin 1160 -> 1296 bytes example/shader.spv.txt | 149 +++++++++++++++++++++-------------------- src/Result.zig | 44 ++++++++++-- src/opcodes.zig | 26 +++++-- test/arrays.zig | 30 +++++++++ test/loops.zig | 45 ------------- test/root.zig | 1 + 9 files changed, 187 insertions(+), 143 deletions(-) create mode 100644 test/arrays.zig diff --git a/example/main.zig b/example/main.zig index 169a6cc..c4aede2 100644 --- a/example/main.zig +++ b/example/main.zig @@ -17,9 +17,11 @@ pub fn main() !void { defer rt.deinit(allocator); try rt.callEntryPoint(allocator, try rt.getEntryPointByName("main")); - var output: [4]f32 = undefined; - try rt.readOutput(f32, output[0..output.len], try rt.getResultByName("color")); - std.log.info("Output: Vec4{any}", .{output}); + var value: f32 = undefined; + var value2: f32 = undefined; + try rt.readOutput(f32, @as([*]f32, @ptrCast(&value))[0..1], try rt.getResultByName("value")); + try rt.readOutput(f32, @as([*]f32, @ptrCast(&value2))[0..1], try rt.getResultByName("value2")); + std.log.info("Output: {d} {d}", .{ value, value2 }); } std.log.info("Successfully executed", .{}); } diff --git a/example/shader.nzsl b/example/shader.nzsl index 2c15105..4c68214 100644 --- a/example/shader.nzsl +++ b/example/shader.nzsl @@ -1,22 +1,27 @@ [nzsl_version("1.1")] -[feature(float64)] module; struct FragOut { - [location(0)] color: vec4[f32] + [location(0)] value: f32, + [location(1)] value2: f32 +} + +fn Half(inout color: vec3[f32], out value: f32, in inValue: f32, inValue2: f32) +{ + color *= 2.0; + value = 10.0; } [entry(frag)] fn main() -> FragOut { - let value: f32 = 1.0; - for i in 1 -> 5 { - if (i == 3) - continue; - value *= f32(i); - } - let output: FragOut; - output.color = vec4[f32](value, value, value, value); - return output; + let output: FragOut; + let mainColor = vec3[f32](1.0, 1.0, 1.0); + let inValue = 2.0; + let inValue2 = 1.0; + Half(inout mainColor, out output.value2, in inValue, inValue2); + output.value = mainColor.x; + + return output; } diff --git a/example/shader.spv b/example/shader.spv index 0709c8c8f3a3ef741f465de18857f6e40ddef3b3..ac2a6756f6b341aef52f23fb16ff3af210e607eb 100644 GIT binary patch literal 1296 zcmZ9MOHUM05Jrm`1{4(rk(Uqbag>KB2qyT73LBiAvSB|9G$aTKifh6T;P<*Q@tmHn zq%$|ERDJc;>sH@%v(X)o7>TR)O1zH2nT`gYh{G{tYhywKLhUdPrjqdKJ{6@5O4mHBu8w%*gn1599^&{ee(Le|4g-;Iqum27sxz} zn-Z%Fu(5-E3~;N$#&lrD(AG6hE@d5$G3Ii16W=IdvDc~gYp#7J(Aj$l>@Lk$;jQ<9`QRiH-cV6{C?K+F6J7OJ)dLCnQL!x)?LRoXOC~?E?yw+ z*Y{++*qE&K65ARFL_6~aqR*2xHnFYY8?=VlIBWQ(Um@~Y!=H>kkMX`$eaZ7HDS7WI K@7vXvZ{|PKVmV3x literal 1160 zcmZ9LO;1x%5QfK=f*{Z$Uy2B~6huB1NQ}`axB+(P#yv5FkSI5)x+f<58F&0S1QHUT zr@be+=}G3!yzhLT>1nmn8i;rhe;UiN6Wucw6_^P15PCGK9fw>!`lAp182NF0cCMoz zX%HhvF|29~qNA}#Y%RW?w11xE=kKzu%`NE~ta1D8vPWc ze68nh%zp!N9(U()4>x?r(Z+g*3B-J{Gfwv4sSmVGgSqZR+dS{9ZH{-lrPmX* zJ=GuR;r(Y3;}d?4ZO#?*x(9z(W8|;NnL$58Ja=IIPZ4=*Yo}TZ*w+4A)M{bNxzm5l zHjnmLM_-0C5$k9>v%SRfVspf5`?%Xh#QUedOW5|!3;zpjxl86Sei<=GKJ88}<-f!> z|AKgTw1UW`o$8Y-&*z-w9lMV--zs*R&;DyYc)bU26!D?OXDXuKx@1*4i#OR43l|DR |v| v, .Matrix => |m| m, - .Array => |_| unreachable, + .Array => |a| a, .Structure => |s| s, else => null, }; @@ -120,8 +120,14 @@ pub const Value = union(Type) { } break :blk self; }, - .Array => |_| { - unreachable; + .Array => |a| blk: { + var self: Value = .{ .Array = allocator.alloc(Value, member_count) catch return RuntimeError.OutOfMemory }; + errdefer self.deinit(allocator); + + for (self.Array) |*value| { + value.* = try Value.init(allocator, results, a.components_type_word); + } + break :blk self; }, .Structure => |s| blk: { var self: Value = .{ .Structure = allocator.alloc(Value, member_count) catch return RuntimeError.OutOfMemory }; @@ -155,6 +161,13 @@ pub const Value = union(Type) { break :blk values; }, }, + .Array => |a| .{ + .Array = blk: { + const values = allocator.dupe(Value, a) catch return RuntimeError.OutOfMemory; + for (values, a) |*new_value, value| new_value.* = try value.dupe(allocator); + break :blk values; + }, + }, .Structure => |s| .{ .Structure = blk: { const values = allocator.dupe(Value, s) catch return RuntimeError.OutOfMemory; @@ -176,6 +189,10 @@ pub const Value = union(Type) { for (values) |*value| value.deinit(allocator); allocator.free(values); }, + .Array => |values| { + for (values) |*value| value.deinit(allocator); + allocator.free(values); + }, .Structure => |values| { for (values) |*value| value.deinit(allocator); allocator.free(values); @@ -208,7 +225,11 @@ pub const VariantData = union(Variant) { column_type: Type, member_count: SpvWord, }, - Array: struct {}, + Array: struct { + components_type_word: SpvWord, + components_type: Type, + member_count: SpvWord, + }, RuntimeArray: struct {}, Structure: struct { members_type_word: []const SpvWord, @@ -433,6 +454,7 @@ pub fn getMemberCounts(self: *const Self) usize { .Bool, .Int, .Float, .Image, .Sampler => return 1, .Vector => |v| return v.member_count, .Matrix => |m| return m.member_count, + .Array => |a| return a.member_count, .SampledImage => return 2, .Structure => |s| return s.members.len, .Function => |f| return f.params.len, @@ -447,6 +469,7 @@ pub fn getMemberCounts(self: *const Self) usize { pub fn initValue(allocator: std.mem.Allocator, member_count: usize, results: []const Self, resolved: *const Self) RuntimeError!Value { return switch (resolved.variant.?) { .Type => |t| switch (t) { + .Void => .{ .Void = .{} }, .Bool => .{ .Bool = false }, .Int => .{ .Int = .{ .uint64 = 0 } }, .Float => .{ .Float = .{ .float64 = 0.0 } }, @@ -466,7 +489,14 @@ pub fn initValue(allocator: std.mem.Allocator, member_count: usize, results: []c } break :blk value; }, - .Array => |_| RuntimeError.ToDo, + .Array => |a| blk: { + const value: Value = .{ .Array = allocator.alloc(Value, member_count) catch return RuntimeError.OutOfMemory }; + errdefer allocator.free(value.Vector); + for (value.Array) |*val| { + val.* = try Value.init(allocator, results, a.components_type_word); + } + break :blk value; + }, .Structure => |s| blk: { const value: Value = .{ .Structure = allocator.alloc(Value, member_count) catch return RuntimeError.OutOfMemory }; errdefer allocator.free(value.Structure); diff --git a/src/opcodes.zig b/src/opcodes.zig index bffabcc..713f181 100644 --- a/src/opcodes.zig +++ b/src/opcodes.zig @@ -99,6 +99,7 @@ pub const SetupDispatcher = block: { .SatConvertUToS = autoSetupConstant, .Source = opSource, .SourceExtension = opSourceExtension, + .TypeArray = opTypeArray, .TypeBool = opTypeBool, .TypeFloat = opTypeFloat, .TypeFunction = opTypeFunction, @@ -505,7 +506,10 @@ fn opAccessChain(_: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) Runtim if (i.uint32 > m.len) return RuntimeError.InvalidSpirV; value_ptr = &m[i.uint32]; }, - .Array => |_| return RuntimeError.ToDo, + .Array => |a| { + if (i.uint32 > a.len) return RuntimeError.InvalidSpirV; + value_ptr = &a[i.uint32]; + }, .Structure => |s| { if (i.uint32 > s.len) return RuntimeError.InvalidSpirV; value_ptr = &s[i.uint32]; @@ -866,6 +870,23 @@ fn opStore(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void { copyValue(try rt.results[ptr_id].getValue(), try rt.results[val_id].getValue()); } +fn opTypeArray(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void { + const id = try rt.it.next(); + const components_type_word = try rt.it.next(); + rt.mod.results[id].variant = .{ + .Type = .{ + .Array = .{ + .components_type_word = components_type_word, + .components_type = switch ((try rt.mod.results[components_type_word].getVariant()).*) { + .Type => |t| @as(Result.Type, t), + else => return RuntimeError.InvalidSpirV, + }, + .member_count = try rt.it.next(), + }, + }, + }; +} + fn opTypeBool(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void { const id = try rt.it.next(); rt.mod.results[id].variant = .{ @@ -1076,9 +1097,6 @@ fn setupConstant(allocator: std.mem.Allocator, rt: *Runtime) RuntimeError!*Resul const resolved = rt.mod.results[res_type].resolveType(rt.mod.results); const member_count = resolved.getMemberCounts(); - if (member_count == 0) { - return RuntimeError.InvalidSpirV; - } target.variant = .{ .Constant = .{ .value = try Result.initValue(allocator, member_count, rt.mod.results, resolved), diff --git a/test/arrays.zig b/test/arrays.zig new file mode 100644 index 0000000..bf5d592 --- /dev/null +++ b/test/arrays.zig @@ -0,0 +1,30 @@ +const std = @import("std"); +const root = @import("root.zig"); +const compileNzsl = root.compileNzsl; +const case = root.case; + +test "Simple array" { + const allocator = std.testing.allocator; + const shader = + \\ [nzsl_version("1.1")] + \\ module; + \\ + \\ struct FragOut + \\ { + \\ [location(0)] color: vec4[f32] + \\ } + \\ + \\ [entry(frag)] + \\ fn main() -> FragOut + \\ { + \\ let value = array[f32](4.0, 3.0, 2.0, 1.0); + \\ let output: FragOut; + \\ output.color = vec4[f32](value[0], value[1], value[2], value[3]); + \\ return output; + \\ } + ; + const code = try compileNzsl(allocator, shader); + defer allocator.free(code); + + try case.expectOutput(f32, 4, code, "color", &.{ 4, 3, 2, 1 }); +} diff --git a/test/loops.zig b/test/loops.zig index 05e6714..30c335e 100644 --- a/test/loops.zig +++ b/test/loops.zig @@ -3,51 +3,6 @@ const root = @import("root.zig"); const compileNzsl = root.compileNzsl; const case = root.case; -test "Simple for loop" { - const allocator = std.testing.allocator; - const base = @mod(case.random(f32), 5.0); - const iterations = 5; - - var expected = base; - for (1..iterations) |i| { - expected *= @floatFromInt(i); - } - - const shader = try std.fmt.allocPrint( - allocator, - \\ [nzsl_version("1.1")] - \\ [feature(float64)] - \\ module; - \\ - \\ struct FragOut - \\ {{ - \\ [location(0)] color: vec4[f32] - \\ }} - \\ - \\ [entry(frag)] - \\ fn main() -> FragOut - \\ {{ - \\ let value = f32({d}); - \\ for i in 1 -> {d} - \\ {{ - \\ value *= f32(i); - \\ }} - \\ let output: FragOut; - \\ output.color = vec4[f32](value, value, value, value); - \\ return output; - \\ }} - , - .{ - base, - iterations, - }, - ); - defer allocator.free(shader); - const code = try compileNzsl(allocator, shader); - defer allocator.free(code); - try case.expectOutput(f32, 4, code, "color", &.{ expected, expected, expected, expected }); -} - test "Simple while loop" { const allocator = std.testing.allocator; const base = @mod(case.random(f32), 5.0); diff --git a/test/root.zig b/test/root.zig index 4741193..9b057e7 100644 --- a/test/root.zig +++ b/test/root.zig @@ -56,6 +56,7 @@ pub const case = struct { }; test { + std.testing.refAllDecls(@import("arrays.zig")); std.testing.refAllDecls(@import("basics.zig")); std.testing.refAllDecls(@import("branching.zig")); std.testing.refAllDecls(@import("casts.zig"));