From c5225e3a4552e396e02912b8d3d5c8ed72269b97 Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Wed, 21 Jan 2026 00:35:48 +0100 Subject: [PATCH] working on example --- build.zig | 1 + example/main.zig | 68 ++++++++++++++----------------- example/shader.nzsl | 16 +++++--- example/shader.spv | Bin 560 -> 1168 bytes example/shader.spv.txt | 89 ++++++++++++++++++++++++++++------------- src/Result.zig | 19 +-------- src/Runtime.zig | 81 ++++++++++++++++++++++++++----------- src/opcodes.zig | 21 ++++------ 8 files changed, 171 insertions(+), 124 deletions(-) diff --git a/build.zig b/build.zig index ca86383..054add2 100644 --- a/build.zig +++ b/build.zig @@ -31,6 +31,7 @@ pub fn build(b: *std.Build) void { .optimize = optimize, .imports = &.{ .{ .name = "spv", .module = mod }, + .{ .name = "pretty", .module = pretty.module("pretty") }, }, }), }); diff --git a/example/main.zig b/example/main.zig index 7d91430..f0f400f 100644 --- a/example/main.zig +++ b/example/main.zig @@ -17,7 +17,7 @@ pub fn main() !void { try sdl3.init(init_flags); defer sdl3.quit(init_flags); - const window = try sdl3.video.Window.init("Hello SDL3", screen_width, screen_height, .{}); + const window = try sdl3.video.Window.init("Hello triangle", screen_width, screen_height, .{}); defer window.deinit(); const allocator = gpa.allocator(); @@ -32,19 +32,10 @@ pub fn main() !void { try surface.lock(); defer surface.unlock(); - const map = surface.getPixels() orelse return; + var pixel_map: [*]u32 = @as([*]u32, @ptrCast(@alignCast((surface.getPixels() orelse return).ptr))); - var pool: std.Thread.Pool = undefined; - try pool.init(.{ - .allocator = allocator, - .n_jobs = 16384, - }); - defer pool.deinit(); - - var wait_group: std.Thread.WaitGroup = .{}; - - const margin_x = @divTrunc(screen_width, 5); - const margin_y = @divTrunc(screen_height, 5); + const margin_x = @divTrunc(screen_width, 3); + const margin_y = @divTrunc(screen_height, 3); const top_y = margin_y; const bottom_y = (screen_height - 1) - margin_y; const center_x = @divTrunc(screen_width, 2); @@ -58,38 +49,37 @@ pub fn main() !void { const x1 = std.math.clamp(center_x + half_w, 0, screen_width - 1); for (x0..x1) |x| { - pool.spawnWg(&wait_group, run, .{ allocator, &module, map, surface, x, y }); + var rt = try spv.Runtime.init(allocator, &module); + defer rt.deinit(allocator); + + var output: [4]f32 = undefined; + + const entry = try rt.getEntryPointByName("main"); + const color = try rt.getResultByName("color"); + const dim = try rt.getResultByName("dim"); + const pos = try rt.getResultByName("pos"); + + try rt.writeInput(f32, &.{ @floatFromInt(x1 - x0), @floatFromInt(bottom_y - top_y) }, dim); + try rt.writeInput(f32, &.{ @floatFromInt(x), @floatFromInt(y) }, pos); + + try rt.callEntryPoint(allocator, entry); + try rt.readOutput(f32, output[0..], color); + + const rgba = surface.mapRgba( + @intFromFloat(output[0] * 255.0), + @intFromFloat(output[1] * 255.0), + @intFromFloat(output[2] * 255.0), + @intFromFloat(output[3] * 255.0), + ); + + pixel_map[(y * surface.getWidth()) + x] = rgba.value; } } - pool.waitAndWork(&wait_group); } try window.updateSurface(); - std.Thread.sleep(5_000_000_000); + std.Thread.sleep(10_000_000_000); } std.log.info("Successfully executed", .{}); } - -fn run(allocator: std.mem.Allocator, module: *spv.Module, map: []u8, surface: sdl3.surface.Surface, x: usize, y: usize) void { - var rt = spv.Runtime.init(allocator, module) catch |err| std.debug.panic("Failed with error {s}", .{@errorName(err)}); - defer rt.deinit(allocator); - - var output: [4]f32 = undefined; - - const entry = rt.getEntryPointByName("main") catch |err| std.debug.panic("Failed with error {s}", .{@errorName(err)}); - const color = rt.getResultByName("color") catch |err| std.debug.panic("Failed with error {s}", .{@errorName(err)}); - - rt.callEntryPoint(allocator, entry) catch |err| std.debug.panic("Failed with error {s}", .{@errorName(err)}); - rt.readOutput(f32, output[0..], color) catch |err| std.debug.panic("Failed with error {s}", .{@errorName(err)}); - - const rgba = surface.mapRgba( - @intFromFloat(output[0] * 255.0), - @intFromFloat(output[1] * 255.0), - @intFromFloat(output[2] * 255.0), - @intFromFloat(output[3] * 255.0), - ); - - var pixel_map: [*]u32 = @as([*]u32, @ptrCast(@alignCast(map.ptr))); - pixel_map[(y * surface.getWidth()) + x] = rgba.value; -} diff --git a/example/shader.nzsl b/example/shader.nzsl index ebb0c2f..7571d06 100644 --- a/example/shader.nzsl +++ b/example/shader.nzsl @@ -3,18 +3,24 @@ module; struct FragIn { - [location(0)] pos: vec2[f32] + [location(0)] dim: vec2[f32], + [location(1)] pos: vec2[f32], } struct FragOut { - [location(0)] color: vec4[f32] + [location(0)] color: vec4[f32] } [entry(frag)] fn main(input: FragIn) -> FragOut { - let output: FragOut; - output.color = vec4[f32](1.0, 0.0, 0.0, 1.0); - return output; + let output: FragOut; + output.color = vec4[f32]( + input.pos.x / input.dim.x, + input.pos.y / input.dim.y, + 1.0, + 1.0 + ); + return output; } diff --git a/example/shader.spv b/example/shader.spv index 77cdfa39206162f69fec0f27eab5b785c0e0412e..361d88032af2ac578246a79f6e35aad3d4bb7d37 100644 GIT binary patch literal 1168 zcmZ9KO;1x%5QfK=i{J+o5m3}}u__>7!p0Ddpc_9{z=l0RW10vhMfS!OKbegQ&(oek z_}yBH^%$P1Xn;gaL~{UWPsUh`pzk9`2i;?dQREiV8c1`% zQH-o+jH9FVo}4Q7zx7YMz2i6a#;XnC3iJ;8WB=g$7b=YwU+!!7=*qY6N$+$JKULy) z&VIsIq3=2D{pj`46+NBDd~N5-T<7~6H}c;dKGEB}HsaAYSKt2n<|qG|>dx-z3{@m% zyx15bmNRDDblK}7^EHSueiqv;*T@{b+_AoVjaQ+K6QAMherrT*wfOe)81LSVF+Ta* z*v7X(on1~b{w~^har;l8?VtQ)@x|LP-bvfsduVgT>}B3G67g$W{w0>Y@o(|Hi@SD~ z^xbv(_Hx(Oc}=vq|C`5sT=1Pin``e`#QOT)W3Kog$aN173g&*csj6@PR^kxugrUfeSL=KVB(qg0$a?yoM8#udUCsL*SA|nYDCWWRqW&Yt{}dHcimzm c`o=r!@V^-H_O#X-vWj?&_r1mbFvTWv32`)w!E|`g;HM$@`?>_MR7Si@cgqx5=A3Z_%(n0-n2u#<(oSpz^ |v| v, - .Matrix => |m| m, - .Array => |a| a, - .Structure => |s| s, + .Vector, .Matrix, .Array, .Structure => |v| v, else => null, }; } @@ -181,19 +178,7 @@ pub const Value = union(Type) { fn deinit(self: *Value, allocator: std.mem.Allocator) void { switch (self.*) { - .Vector => |values| { - for (values) |*value| value.deinit(allocator); - allocator.free(values); - }, - .Matrix => |values| { - for (values) |*value| value.deinit(allocator); - allocator.free(values); - }, - .Array => |values| { - for (values) |*value| value.deinit(allocator); - allocator.free(values); - }, - .Structure => |values| { + .Vector, .Matrix, .Array, .Structure => |values| { for (values) |*value| value.deinit(allocator); allocator.free(values); }, diff --git a/src/Runtime.zig b/src/Runtime.zig index 11f3519..9370e21 100644 --- a/src/Runtime.zig +++ b/src/Runtime.zig @@ -14,20 +14,16 @@ const WordIterator = @import("WordIterator.zig"); const Self = @This(); pub const RuntimeError = error{ - InvalidSpirV, - UnsupportedSpirV, - OutOfMemory, - Unreachable, - Killed, - InvalidEntryPoint, - ToDo, DivisionByZero, + InvalidEntryPoint, + InvalidSpirV, InvalidValueType, -}; - -pub const ReadOutputError = error{ + Killed, NotFound, - InvalidValueType, + OutOfMemory, + ToDo, + Unreachable, + UnsupportedSpirV, }; pub const Function = struct { @@ -141,7 +137,6 @@ pub fn callEntryPoint(self: *Self, allocator: std.mem.Allocator, entry_point_ind self.it = it_tmp; } else { self.it.did_jump = false; - //_ = self.it.skip(); } } @@ -153,11 +148,19 @@ pub fn callEntryPoint(self: *Self, allocator: std.mem.Allocator, entry_point_ind //}) catch return RuntimeError.OutOfMemory; } -pub fn readOutput(self: *const Self, comptime T: type, output: []T, result: SpvWord) ReadOutputError!void { +pub fn readOutput(self: *const Self, comptime T: type, output: []T, result: SpvWord) RuntimeError!void { if (std.mem.indexOf(SpvWord, self.mod.output_locations.items, &.{result})) |_| { try self.readValue(T, output, &self.results[result].variant.?.Variable.value); } else { - return ReadOutputError.NotFound; + return RuntimeError.NotFound; + } +} + +pub fn writeInput(self: *const Self, comptime T: type, input: []const T, result: SpvWord) RuntimeError!void { + if (std.mem.indexOf(SpvWord, self.mod.input_locations.items, &.{result})) |_| { + try self.writeValue(T, input, &self.results[result].variant.?.Variable.value); + } else { + return RuntimeError.NotFound; } } @@ -166,13 +169,13 @@ fn reset(self: *Self) void { self.current_function = null; } -fn readValue(self: *const Self, comptime T: type, output: []T, value: *const Result.Value) ReadOutputError!void { +fn readValue(self: *const Self, comptime T: type, output: []T, value: *const Result.Value) RuntimeError!void { switch (value.*) { .Bool => |b| { if (T == bool) { output[0] = b; } else { - return ReadOutputError.InvalidValueType; + return RuntimeError.InvalidValueType; } }, .Int => |i| { @@ -185,7 +188,7 @@ fn readValue(self: *const Self, comptime T: type, output: []T, value: *const Res u16 => output[0] = i.uint16, u32 => output[0] = i.uint32, u64 => output[0] = i.uint64, - inline else => return ReadOutputError.InvalidValueType, + inline else => return RuntimeError.InvalidValueType, } }, .Float => |f| { @@ -193,13 +196,45 @@ fn readValue(self: *const Self, comptime T: type, output: []T, value: *const Res f16 => output[0] = f.float16, f32 => output[0] = f.float32, f64 => output[0] = f.float64, - inline else => return ReadOutputError.InvalidValueType, + inline else => return RuntimeError.InvalidValueType, } }, - .Vector => |values| for (values, 0..) |v, i| try self.readValue(T, output[i..], &v), - .Matrix => |values| for (values, 0..) |v, i| try self.readValue(T, output[i..], &v), - .Array => |values| for (values, 0..) |v, i| try self.readValue(T, output[i..], &v), // Doubt if this is allowed - .Structure => |values| for (values, 0..) |v, i| try self.readValue(T, output[i..], &v), - else => return ReadOutputError.InvalidValueType, + .Vector, .Matrix, .Array, .Structure => |values| for (values, 0..) |v, i| try self.readValue(T, output[i..], &v), + else => return RuntimeError.InvalidValueType, + } +} + +fn writeValue(self: *const Self, comptime T: type, input: []const T, value: *Result.Value) RuntimeError!void { + switch (value.*) { + .Bool => |*b| { + if (T == bool) { + b.* = input[0]; + } else { + return RuntimeError.InvalidValueType; + } + }, + .Int => |*i| { + switch (T) { + i8 => i.sint8 = input[0], + i16 => i.sint16 = input[0], + i32 => i.sint32 = input[0], + i64 => i.sint64 = input[0], + u8 => i.uint8 = input[0], + u16 => i.uint16 = input[0], + u32 => i.uint32 = input[0], + u64 => i.uint64 = input[0], + inline else => return RuntimeError.InvalidValueType, + } + }, + .Float => |*f| { + switch (T) { + f16 => f.float16 = input[0], + f32 => f.float32 = input[0], + f64 => f.float64 = input[0], + inline else => return RuntimeError.InvalidValueType, + } + }, + .Vector, .Matrix, .Array, .Structure => |*values| for (values.*, 0..) |*v, i| try self.writeValue(T, input[i..], v), + else => return RuntimeError.InvalidValueType, } } diff --git a/src/opcodes.zig b/src/opcodes.zig index 121655c..9c24334 100644 --- a/src/opcodes.zig +++ b/src/opcodes.zig @@ -169,6 +169,7 @@ pub const RuntimeDispatcher = block: { .ConvertFToU = ConversionEngine(.Float, .UInt).op, .ConvertSToF = ConversionEngine(.SInt, .Float).op, .ConvertUToF = ConversionEngine(.UInt, .Float).op, + .CopyMemory = opCopyMemory, .FAdd = MathEngine(.Float, .Add).op, .FConvert = ConversionEngine(.Float, .Float).op, .FDiv = MathEngine(.Float, .Div).op, @@ -631,22 +632,10 @@ fn opAccessChain(_: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) Runtim switch (member_value.*) { .Int => |i| { switch (value_ptr.*) { - .Vector => |v| { + .Vector, .Matrix, .Array, .Structure => |v| { if (i.uint32 > v.len) return RuntimeError.InvalidSpirV; value_ptr = &v[i.uint32]; }, - .Matrix => |m| { - if (i.uint32 > m.len) return RuntimeError.InvalidSpirV; - value_ptr = &m[i.uint32]; - }, - .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]; - }, else => return RuntimeError.InvalidSpirV, } }, @@ -752,6 +741,12 @@ fn opConstant(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) R } } +fn opCopyMemory(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void { + const target = try rt.it.next(); + const source = try rt.it.next(); + copyValue(try rt.results[target].getValue(), try rt.results[source].getValue()); +} + fn opDecorate(allocator: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void { const target = try rt.it.next(); const decoration_type = try rt.it.nextAs(spv.SpvDecoration);