diff --git a/.gitignore b/.gitignore index f9c7b4e..afa497c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .zig-cache/ zig-out/ +zig-pkg/ .gdb_history *.o vgcore* diff --git a/build.zig b/build.zig index 8dfe6a2..0c9f361 100644 --- a/build.zig +++ b/build.zig @@ -30,7 +30,7 @@ pub fn build(b: *std.Build) void { const no_example = b.option(bool, "no-example", "skips example dependencies fetch") orelse false; - if (!no_example) { + if (!no_example and false) { const sdl3 = b.lazyDependency("sdl3", .{ .target = target, .optimize = optimize }) orelse return; const example_exe = b.addExecutable(.{ .name = "spirv_interpreter_example", diff --git a/build.zig.zon b/build.zig.zon index 134bdf4..7dcbb0b 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -6,22 +6,22 @@ .url = "git+https://github.com/zig-gamedev/zmath.git#3a5955b2b72cd081563fbb084eff05bffd1e3fbb", .hash = "zmath-0.11.0-dev-wjwivdMsAwD-xaLj76YHUq3t9JDH-X16xuMTmnDzqbu2", }, - .pretty = .{ // For debugging purposes - .url = "git+https://github.com/Kbz-8/pretty#117674465efd4d07d5ae9d9d8ca59c2c323a65ba", - .hash = "pretty-0.10.6-Tm65r99UAQDEJMgZysD10qE8dinBHr064fPM6YkxVPfB", - }, .NZSL = .{ // For unit tests - .url = "git+https://git.kbz8.me/kbz_8/NZigSL#5377dbdf9935b0de767f76ea4650e7aba4516b32", - .hash = "NZSL-1.1.2-N0xSVMt6AAC1ncQHA_RafnclWolDA477iTnFmZgdvxd-", + .url = "git+https://git.kbz8.me/kbz_8/NZigSL#ab95fc3734da46079fda2a4cd0f14143d92bf633", + .hash = "NZSL-1.1.2-N0xSVCR7AACeI_Wa6JPggJzy9_MPCpWC-2OHkMowwX-7", .lazy = true, }, - .sdl3 = .{ - .url = "git+https://codeberg.org/7Games/zig-sdl3?ref=v0.1.6#9c1842246c59f03f87ba59b160ca7e3d5e5ce972", - .hash = "sdl3-0.1.6-NmT1Q5sQJgCzT6hLj7WOSrwxE0Qsef1wIkDopbOOFru0", - .lazy = true, + //.sdl3 = .{ + // .url = "git+https://codeberg.org/7Games/zig-sdl3?ref=v0.1.6#9c1842246c59f03f87ba59b160ca7e3d5e5ce972", + // .hash = "sdl3-0.1.6-NmT1Q5sQJgCzT6hLj7WOSrwxE0Qsef1wIkDopbOOFru0", + // .lazy = true, + //}, + .pretty = .{ + .url = "git+https://github.com/Kbz-8/pretty#d87459a829fe0ae82b408155053e1933e2a16a15", + .hash = "pretty-0.10.6-Tm65rw5VAQDqJ-sbE6eoU-yOAr7kzUmAUrUQd7Wzaa9Q", }, }, - .minimum_zig_version = "0.15.2", + .minimum_zig_version = "0.16.0", .paths = .{ "build.zig", "build.zig.zon", diff --git a/src/Module.zig b/src/Module.zig index 2642b35..3558139 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -127,45 +127,6 @@ pub fn init(allocator: std.mem.Allocator, source: []const SpvWord, options: Modu try self.pass(allocator); // Setup pass try self.applyDecorations(); - if (std.process.hasEnvVarConstant("SPIRV_INTERPRETER_DEBUG_LOGS")) { - var capability_set_names: std.ArrayList([]const u8) = .empty; - defer capability_set_names.deinit(allocator); - - var it = self.capabilities.iterator(); - while (it.next()) |cap| { - capability_set_names.append(allocator, @tagName(cap)) catch return ModuleError.OutOfMemory; - } - - const capabilities = std.mem.join(allocator, ", ", capability_set_names.items) catch return ModuleError.OutOfMemory; - defer allocator.free(capabilities); - - var entry_points_names = std.ArrayList([]const u8).initCapacity(allocator, self.entry_points.items.len) catch return ModuleError.OutOfMemory; - defer entry_points_names.deinit(allocator); - - for (self.entry_points.items) |entry_point| { - entry_points_names.appendAssumeCapacity(entry_point.name); - } - - const entry_points = std.mem.join(allocator, ", ", entry_points_names.items) catch return ModuleError.OutOfMemory; - defer allocator.free(entry_points); - - std.log.scoped(.SPIRV_Interpreter).debug( - \\Loaded shader module with infos: - \\ SPIR-V version: {d}.{d} - \\ Generator: {s} (ID {d}), encoded version 0x{X} - \\ Capabilities: [{s}] - \\ Entry points: [{s}] - , .{ - self.version_major, - self.version_minor, - spv.vendorName(self.generator_id), - self.generator_id, - self.generator_version, - capabilities, - entry_points, - }); - } - return self; } diff --git a/src/Value.zig b/src/Value.zig index 0d0e77b..5481123 100644 --- a/src/Value.zig +++ b/src/Value.zig @@ -667,13 +667,31 @@ pub const Value = union(Type) { .Vector => |lanes| (try getPrimitiveField(T, bits, &lanes[lane_index])).*, - .Vector4i32 => |vec| if (bits == 32) @as(TT, @bitCast(vec[lane_index])) else return RuntimeError.InvalidSpirV, - .Vector3i32 => |vec| if (bits == 32) @as(TT, @bitCast(vec[lane_index])) else return RuntimeError.InvalidSpirV, - .Vector2i32 => |vec| if (bits == 32) @as(TT, @bitCast(vec[lane_index])) else return RuntimeError.InvalidSpirV, + .Vector2i32 => |*vec| switch (lane_index) { + inline 0...1 => |i| if (bits == 32) @as(TT, @bitCast(vec[i])) else return RuntimeError.InvalidSpirV, + else => return RuntimeError.InvalidSpirV, + }, + .Vector3i32 => |*vec| switch (lane_index) { + inline 0...2 => |i| if (bits == 32) @as(TT, @bitCast(vec[i])) else return RuntimeError.InvalidSpirV, + else => return RuntimeError.InvalidSpirV, + }, + .Vector4i32 => |*vec| switch (lane_index) { + inline 0...3 => |i| if (bits == 32) @as(TT, @bitCast(vec[i])) else return RuntimeError.InvalidSpirV, + else => return RuntimeError.InvalidSpirV, + }, - .Vector4u32 => |vec| if (bits == 32) @as(TT, @bitCast(vec[lane_index])) else return RuntimeError.InvalidSpirV, - .Vector3u32 => |vec| if (bits == 32) @as(TT, @bitCast(vec[lane_index])) else return RuntimeError.InvalidSpirV, - .Vector2u32 => |vec| if (bits == 32) @as(TT, @bitCast(vec[lane_index])) else return RuntimeError.InvalidSpirV, + .Vector2u32 => |*vec| switch (lane_index) { + inline 0...1 => |i| if (bits == 32) @as(TT, @bitCast(vec[i])) else return RuntimeError.InvalidSpirV, + else => return RuntimeError.InvalidSpirV, + }, + .Vector3u32 => |*vec| switch (lane_index) { + inline 0...2 => |i| if (bits == 32) @as(TT, @bitCast(vec[i])) else return RuntimeError.InvalidSpirV, + else => return RuntimeError.InvalidSpirV, + }, + .Vector4u32 => |*vec| switch (lane_index) { + inline 0...3 => |i| if (bits == 32) @as(TT, @bitCast(vec[i])) else return RuntimeError.InvalidSpirV, + else => return RuntimeError.InvalidSpirV, + }, else => RuntimeError.InvalidSpirV, }; @@ -685,13 +703,31 @@ pub const Value = union(Type) { .Vector => |lanes| try setScalarLaneValue(T, bits, &lanes[lane_index], value), - .Vector2i32 => |*vec| vec[lane_index] = if (bits == 32) @bitCast(value) else return RuntimeError.InvalidSpirV, - .Vector3i32 => |*vec| vec[lane_index] = if (bits == 32) @bitCast(value) else return RuntimeError.InvalidSpirV, - .Vector4i32 => |*vec| vec[lane_index] = if (bits == 32) @bitCast(value) else return RuntimeError.InvalidSpirV, + .Vector2i32 => |*vec| switch (lane_index) { + inline 0...1 => |i| vec[i] = if (bits == 32) @bitCast(value) else return RuntimeError.InvalidSpirV, + else => return RuntimeError.InvalidSpirV, + }, + .Vector3i32 => |*vec| switch (lane_index) { + inline 0...2 => |i| vec[i] = if (bits == 32) @bitCast(value) else return RuntimeError.InvalidSpirV, + else => return RuntimeError.InvalidSpirV, + }, + .Vector4i32 => |*vec| switch (lane_index) { + inline 0...3 => |i| vec[i] = if (bits == 32) @bitCast(value) else return RuntimeError.InvalidSpirV, + else => return RuntimeError.InvalidSpirV, + }, - .Vector2u32 => |*vec| vec[lane_index] = if (bits == 32) @bitCast(value) else return RuntimeError.InvalidSpirV, - .Vector3u32 => |*vec| vec[lane_index] = if (bits == 32) @bitCast(value) else return RuntimeError.InvalidSpirV, - .Vector4u32 => |*vec| vec[lane_index] = if (bits == 32) @bitCast(value) else return RuntimeError.InvalidSpirV, + .Vector2u32 => |*vec| switch (lane_index) { + inline 0...1 => |i| vec[i] = if (bits == 32) @bitCast(value) else return RuntimeError.InvalidSpirV, + else => return RuntimeError.InvalidSpirV, + }, + .Vector3u32 => |*vec| switch (lane_index) { + inline 0...2 => |i| vec[i] = if (bits == 32) @bitCast(value) else return RuntimeError.InvalidSpirV, + else => return RuntimeError.InvalidSpirV, + }, + .Vector4u32 => |*vec| switch (lane_index) { + inline 0...3 => |i| vec[i] = if (bits == 32) @bitCast(value) else return RuntimeError.InvalidSpirV, + else => return RuntimeError.InvalidSpirV, + }, else => return RuntimeError.InvalidSpirV, } diff --git a/src/opcodes.zig b/src/opcodes.zig index c33e5ed..93fb032 100644 --- a/src/opcodes.zig +++ b/src/opcodes.zig @@ -646,8 +646,8 @@ fn CondOperator(comptime T: PrimitiveType, comptime Op: CondOp) type { comptime ElemT: type, comptime N: usize, dst: []Value, - op1: *[N]ElemT, - op2: *[N]ElemT, + op1: *@Vector(N, ElemT), + op2: *@Vector(N, ElemT), ) RuntimeError!void { inline for (0..N) |i| dst[i].Bool = try operationBinary(ElemT, op1[i], op2[i]); } @@ -656,7 +656,7 @@ fn CondOperator(comptime T: PrimitiveType, comptime Op: CondOp) type { comptime ElemT: type, comptime N: usize, dst: []Value, - op1: *[N]ElemT, + op1: *@Vector(N, ElemT), ) RuntimeError!void { inline for (0..N) |i| dst[i].Bool = try operationUnary(ElemT, op1[i]); } @@ -796,11 +796,11 @@ fn ConversionEngine(comptime from_kind: PrimitiveType, comptime to_kind: Primiti } } - fn castSIMDVector(comptime ToT: type, comptime N: usize, dst_arr: *[N]ToT, src_arr: *const [N]ToT) void { + fn castSIMDVector(comptime ToT: type, comptime N: usize, dst_arr: *@Vector(N, ToT), src_arr: *const @Vector(N, ToT)) void { inline for (0..N) |i| dst_arr[i] = std.math.lossyCast(ToT, src_arr[i]); } - fn castSIMDVectorFromOther(comptime ToT: type, comptime FromT: type, comptime N: usize, dst_arr: *[N]ToT, src_arr: *const [N]FromT) void { + fn castSIMDVectorFromOther(comptime ToT: type, comptime FromT: type, comptime N: usize, dst_arr: *@Vector(N, ToT), src_arr: *const @Vector(N, FromT)) void { inline for (0..N) |i| dst_arr[i] = std.math.lossyCast(ToT, src_arr[i]); } }; @@ -1320,41 +1320,41 @@ fn opAccessChain(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime is_owner_of_uniform_slice = true; uniform_slice_window = arr.data[arr.getOffsetOfIndex(i.value.uint32)..]; }, - .Vector4f32 => |*v| { - if (i.value.uint32 >= 4) return RuntimeError.OutOfBounds; - break :blk .{ .Pointer = .{ .ptr = .{ .f32_ptr = &v[i.value.uint32] } } }; + .Vector4f32 => |*v| switch (i.value.uint32) { + inline 0...3 => |idx| break :blk .{ .Pointer = .{ .ptr = .{ .f32_ptr = &v[idx] } } }, + else => return RuntimeError.InvalidSpirV, }, - .Vector3f32 => |*v| { - if (i.value.uint32 >= 3) return RuntimeError.OutOfBounds; - break :blk .{ .Pointer = .{ .ptr = .{ .f32_ptr = &v[i.value.uint32] } } }; + .Vector3f32 => |*v| switch (i.value.uint32) { + inline 0...2 => |idx| break :blk .{ .Pointer = .{ .ptr = .{ .f32_ptr = &v[idx] } } }, + else => return RuntimeError.InvalidSpirV, }, - .Vector2f32 => |*v| { - if (i.value.uint32 >= 2) return RuntimeError.OutOfBounds; - break :blk .{ .Pointer = .{ .ptr = .{ .f32_ptr = &v[i.value.uint32] } } }; + .Vector2f32 => |*v| switch (i.value.uint32) { + inline 0...1 => |idx| break :blk .{ .Pointer = .{ .ptr = .{ .f32_ptr = &v[idx] } } }, + else => return RuntimeError.InvalidSpirV, }, - .Vector4i32 => |*v| { - if (i.value.uint32 >= 4) return RuntimeError.OutOfBounds; - break :blk .{ .Pointer = .{ .ptr = .{ .i32_ptr = &v[i.value.uint32] } } }; + .Vector4i32 => |*v| switch (i.value.uint32) { + inline 0...3 => |idx| break :blk .{ .Pointer = .{ .ptr = .{ .i32_ptr = &v[idx] } } }, + else => return RuntimeError.InvalidSpirV, }, - .Vector3i32 => |*v| { - if (i.value.uint32 >= 3) return RuntimeError.OutOfBounds; - break :blk .{ .Pointer = .{ .ptr = .{ .i32_ptr = &v[i.value.uint32] } } }; + .Vector3i32 => |*v| switch (i.value.uint32) { + inline 0...2 => |idx| break :blk .{ .Pointer = .{ .ptr = .{ .i32_ptr = &v[idx] } } }, + else => return RuntimeError.InvalidSpirV, }, - .Vector2i32 => |*v| { - if (i.value.uint32 >= 2) return RuntimeError.OutOfBounds; - break :blk .{ .Pointer = .{ .ptr = .{ .i32_ptr = &v[i.value.uint32] } } }; + .Vector2i32 => |*v| switch (i.value.uint32) { + inline 0...1 => |idx| break :blk .{ .Pointer = .{ .ptr = .{ .i32_ptr = &v[idx] } } }, + else => return RuntimeError.InvalidSpirV, }, - .Vector4u32 => |*v| { - if (i.value.uint32 >= 4) return RuntimeError.OutOfBounds; - break :blk .{ .Pointer = .{ .ptr = .{ .u32_ptr = &v[i.value.uint32] } } }; + .Vector4u32 => |*v| switch (i.value.uint32) { + inline 0...3 => |idx| break :blk .{ .Pointer = .{ .ptr = .{ .u32_ptr = &v[idx] } } }, + else => return RuntimeError.InvalidSpirV, }, - .Vector3u32 => |*v| { - if (i.value.uint32 >= 3) return RuntimeError.OutOfBounds; - break :blk .{ .Pointer = .{ .ptr = .{ .u32_ptr = &v[i.value.uint32] } } }; + .Vector3u32 => |*v| switch (i.value.uint32) { + inline 0...2 => |idx| break :blk .{ .Pointer = .{ .ptr = .{ .u32_ptr = &v[idx] } } }, + else => return RuntimeError.InvalidSpirV, }, - .Vector2u32 => |*v| { - if (i.value.uint32 >= 2) return RuntimeError.OutOfBounds; - break :blk .{ .Pointer = .{ .ptr = .{ .u32_ptr = &v[i.value.uint32] } } }; + .Vector2u32 => |*v| switch (i.value.uint32) { + inline 0...1 => |idx| break :blk .{ .Pointer = .{ .ptr = .{ .u32_ptr = &v[idx] } } }, + else => return RuntimeError.InvalidSpirV, }, else => return RuntimeError.InvalidSpirV, } @@ -1512,15 +1512,42 @@ fn opCompositeExtract(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Ru } switch (composite) { .RuntimeArray => |arr| composite = try arr.createLocalValueFromIndex(arena_allocator, rt.results, member_id), - .Vector4f32 => |v| break :blk .{ .Float = .{ .bit_count = 32, .value = .{ .float32 = v[member_id] } } }, - .Vector3f32 => |v| break :blk .{ .Float = .{ .bit_count = 32, .value = .{ .float32 = v[member_id] } } }, - .Vector2f32 => |v| break :blk .{ .Float = .{ .bit_count = 32, .value = .{ .float32 = v[member_id] } } }, - .Vector4i32 => |v| break :blk .{ .Int = .{ .bit_count = 32, .is_signed = true, .value = .{ .sint32 = v[member_id] } } }, - .Vector3i32 => |v| break :blk .{ .Int = .{ .bit_count = 32, .is_signed = true, .value = .{ .sint32 = v[member_id] } } }, - .Vector2i32 => |v| break :blk .{ .Int = .{ .bit_count = 32, .is_signed = true, .value = .{ .sint32 = v[member_id] } } }, - .Vector4u32 => |v| break :blk .{ .Int = .{ .bit_count = 32, .is_signed = false, .value = .{ .uint32 = v[member_id] } } }, - .Vector3u32 => |v| break :blk .{ .Int = .{ .bit_count = 32, .is_signed = false, .value = .{ .uint32 = v[member_id] } } }, - .Vector2u32 => |v| break :blk .{ .Int = .{ .bit_count = 32, .is_signed = false, .value = .{ .uint32 = v[member_id] } } }, + .Vector4f32 => |v| break :blk .{ .Float = .{ .bit_count = 32, .value = .{ .float32 = switch (member_id) { + inline 0...3 => |idx| v[idx], + else => return RuntimeError.OutOfBounds, + } } } }, + .Vector3f32 => |v| break :blk .{ .Float = .{ .bit_count = 32, .value = .{ .float32 = switch (member_id) { + inline 0...2 => |idx| v[idx], + else => return RuntimeError.OutOfBounds, + } } } }, + .Vector2f32 => |v| break :blk .{ .Float = .{ .bit_count = 32, .value = .{ .float32 = switch (member_id) { + inline 0...1 => |idx| v[idx], + else => return RuntimeError.OutOfBounds, + } } } }, + .Vector4i32 => |v| break :blk .{ .Int = .{ .bit_count = 32, .is_signed = true, .value = .{ .sint32 = switch (member_id) { + inline 0...3 => |idx| v[idx], + else => return RuntimeError.OutOfBounds, + } } } }, + .Vector3i32 => |v| break :blk .{ .Int = .{ .bit_count = 32, .is_signed = true, .value = .{ .sint32 = switch (member_id) { + inline 0...2 => |idx| v[idx], + else => return RuntimeError.OutOfBounds, + } } } }, + .Vector2i32 => |v| break :blk .{ .Int = .{ .bit_count = 32, .is_signed = true, .value = .{ .sint32 = switch (member_id) { + inline 0...1 => |idx| v[idx], + else => return RuntimeError.OutOfBounds, + } } } }, + .Vector4u32 => |v| break :blk .{ .Int = .{ .bit_count = 32, .is_signed = false, .value = .{ .uint32 = switch (member_id) { + inline 0...3 => |idx| v[idx], + else => return RuntimeError.OutOfBounds, + } } } }, + .Vector3u32 => |v| break :blk .{ .Int = .{ .bit_count = 32, .is_signed = false, .value = .{ .uint32 = switch (member_id) { + inline 0...2 => |idx| v[idx], + else => return RuntimeError.OutOfBounds, + } } } }, + .Vector2u32 => |v| break :blk .{ .Int = .{ .bit_count = 32, .is_signed = false, .value = .{ .uint32 = switch (member_id) { + inline 0...1 => |idx| v[idx], + else => return RuntimeError.OutOfBounds, + } } } }, else => return RuntimeError.InvalidValueType, } } @@ -1586,43 +1613,43 @@ fn opCompositeInsert(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Run _ = try elem_value.read(arr.data[elem_offset..]); }, - .Vector4f32 => |*v| { - if (index >= 4 or indices.len != 1) return RuntimeError.InvalidSpirV; - v[index] = (try Value.getPrimitiveField(.Float, 32, @constCast(object_value))).*; + .Vector4f32 => |*v| switch (index) { + inline 0...3 => |i| v[i] = (try Value.getPrimitiveField(.Float, 32, @constCast(object_value))).*, + else => return RuntimeError.InvalidSpirV, }, - .Vector3f32 => |*v| { - if (index >= 3 or indices.len != 1) return RuntimeError.InvalidSpirV; - v[index] = (try Value.getPrimitiveField(.Float, 32, @constCast(object_value))).*; + .Vector3f32 => |*v| switch (index) { + inline 0...2 => |i| v[i] = (try Value.getPrimitiveField(.Float, 32, @constCast(object_value))).*, + else => return RuntimeError.InvalidSpirV, }, - .Vector2f32 => |*v| { - if (index >= 2 or indices.len != 1) return RuntimeError.InvalidSpirV; - v[index] = (try Value.getPrimitiveField(.Float, 32, @constCast(object_value))).*; + .Vector2f32 => |*v| switch (index) { + inline 0...1 => |i| v[i] = (try Value.getPrimitiveField(.Float, 32, @constCast(object_value))).*, + else => return RuntimeError.InvalidSpirV, }, - .Vector4i32 => |*v| { - if (index >= 4 or indices.len != 1) return RuntimeError.InvalidSpirV; - v[index] = (try Value.getPrimitiveField(.SInt, 32, @constCast(object_value))).*; + .Vector4i32 => |*v| switch (index) { + inline 0...3 => |i| v[i] = (try Value.getPrimitiveField(.SInt, 32, @constCast(object_value))).*, + else => return RuntimeError.InvalidSpirV, }, - .Vector3i32 => |*v| { - if (index >= 3 or indices.len != 1) return RuntimeError.InvalidSpirV; - v[index] = (try Value.getPrimitiveField(.SInt, 32, @constCast(object_value))).*; + .Vector3i32 => |*v| switch (index) { + inline 0...2 => |i| v[i] = (try Value.getPrimitiveField(.SInt, 32, @constCast(object_value))).*, + else => return RuntimeError.InvalidSpirV, }, - .Vector2i32 => |*v| { - if (index >= 2 or indices.len != 1) return RuntimeError.InvalidSpirV; - v[index] = (try Value.getPrimitiveField(.SInt, 32, @constCast(object_value))).*; + .Vector2i32 => |*v| switch (index) { + inline 0...1 => |i| v[i] = (try Value.getPrimitiveField(.SInt, 32, @constCast(object_value))).*, + else => return RuntimeError.InvalidSpirV, }, - .Vector4u32 => |*v| { - if (index >= 4 or indices.len != 1) return RuntimeError.InvalidSpirV; - v[index] = (try Value.getPrimitiveField(.UInt, 32, @constCast(object_value))).*; + .Vector4u32 => |*v| switch (index) { + inline 0...3 => |i| v[i] = (try Value.getPrimitiveField(.UInt, 32, @constCast(object_value))).*, + else => return RuntimeError.InvalidSpirV, }, - .Vector3u32 => |*v| { - if (index >= 3 or indices.len != 1) return RuntimeError.InvalidSpirV; - v[index] = (try Value.getPrimitiveField(.UInt, 32, @constCast(object_value))).*; + .Vector3u32 => |*v| switch (index) { + inline 0...2 => |i| v[i] = (try Value.getPrimitiveField(.UInt, 32, @constCast(object_value))).*, + else => return RuntimeError.InvalidSpirV, }, - .Vector2u32 => |*v| { - if (index >= 2 or indices.len != 1) return RuntimeError.InvalidSpirV; - v[index] = (try Value.getPrimitiveField(.UInt, 32, @constCast(object_value))).*; + .Vector2u32 => |*v| switch (index) { + inline 0...1 => |i| v[i] = (try Value.getPrimitiveField(.UInt, 32, @constCast(object_value))).*, + else => return RuntimeError.InvalidSpirV, }, else => return RuntimeError.InvalidValueType, @@ -2609,95 +2636,77 @@ fn opVectorShuffle(allocator: std.mem.Allocator, _: SpvWord, rt: *Runtime) Runti return lanes[lane_index]; }, - .Vector2f32 => |lanes| { - if (lane_index >= 2) return RuntimeError.InvalidSpirV; - return .{ - .Float = .{ - .bit_count = 32, - .value = .{ .float32 = lanes[lane_index] }, - }, - }; - }, - .Vector3f32 => |lanes| { - if (lane_index >= 3) return RuntimeError.InvalidSpirV; - return .{ - .Float = .{ - .bit_count = 32, - .value = .{ .float32 = lanes[lane_index] }, - }, - }; - }, - .Vector4f32 => |lanes| { - if (lane_index >= 4) return RuntimeError.InvalidSpirV; - return .{ - .Float = .{ - .bit_count = 32, - .value = .{ .float32 = lanes[lane_index] }, - }, - }; - }, + .Vector2f32 => |lanes| return .{ .Float = .{ + .bit_count = 32, + .value = .{ .float32 = switch (lane_index) { + inline 0...1 => |idx| lanes[idx], + else => return RuntimeError.OutOfBounds, + } }, + } }, + .Vector3f32 => |lanes| return .{ .Float = .{ + .bit_count = 32, + .value = .{ .float32 = switch (lane_index) { + inline 0...2 => |idx| lanes[idx], + else => return RuntimeError.OutOfBounds, + } }, + } }, + .Vector4f32 => |lanes| return .{ .Float = .{ + .bit_count = 32, + .value = .{ .float32 = switch (lane_index) { + inline 0...3 => |idx| lanes[idx], + else => return RuntimeError.OutOfBounds, + } }, + } }, - .Vector2i32 => |lanes| { - if (lane_index >= 2) return RuntimeError.InvalidSpirV; - return .{ - .Int = .{ - .bit_count = 32, - .is_signed = true, - .value = .{ .sint32 = lanes[lane_index] }, - }, - }; - }, - .Vector3i32 => |lanes| { - if (lane_index >= 3) return RuntimeError.InvalidSpirV; - return .{ - .Int = .{ - .bit_count = 32, - .is_signed = true, - .value = .{ .sint32 = lanes[lane_index] }, - }, - }; - }, - .Vector4i32 => |lanes| { - if (lane_index >= 4) return RuntimeError.InvalidSpirV; - return .{ - .Int = .{ - .bit_count = 32, - .is_signed = true, - .value = .{ .sint32 = lanes[lane_index] }, - }, - }; - }, + .Vector2i32 => |lanes| return .{ .Int = .{ + .bit_count = 32, + .is_signed = true, + .value = .{ .sint32 = switch (lane_index) { + inline 0...1 => |idx| lanes[idx], + else => return RuntimeError.OutOfBounds, + } }, + } }, + .Vector3i32 => |lanes| return .{ .Int = .{ + .bit_count = 32, + .is_signed = true, + .value = .{ .sint32 = switch (lane_index) { + inline 0...2 => |idx| lanes[idx], + else => return RuntimeError.OutOfBounds, + } }, + } }, + .Vector4i32 => |lanes| return .{ .Int = .{ + .bit_count = 32, + .is_signed = true, + .value = .{ .sint32 = switch (lane_index) { + inline 0...3 => |idx| lanes[idx], + else => return RuntimeError.OutOfBounds, + } }, + } }, - .Vector2u32 => |lanes| { - if (lane_index >= 2) return RuntimeError.InvalidSpirV; - return .{ - .Int = .{ - .bit_count = 32, - .is_signed = false, - .value = .{ .uint32 = lanes[lane_index] }, - }, - }; - }, - .Vector3u32 => |lanes| { - if (lane_index >= 3) return RuntimeError.InvalidSpirV; - return .{ - .Int = .{ - .bit_count = 32, - .is_signed = false, - .value = .{ .uint32 = lanes[lane_index] }, - }, - }; - }, - .Vector4u32 => |lanes| { - if (lane_index >= 4) return RuntimeError.InvalidSpirV; - return .{ - .Int = .{ - .bit_count = 32, - .is_signed = false, - .value = .{ .uint32 = lanes[lane_index] }, - }, - }; - }, + .Vector2u32 => |lanes| return .{ .Int = .{ + .bit_count = 32, + .is_signed = false, + .value = .{ .uint32 = switch (lane_index) { + inline 0...1 => |idx| lanes[idx], + else => return RuntimeError.OutOfBounds, + } }, + } }, + .Vector3u32 => |lanes| return .{ .Int = .{ + .bit_count = 32, + .is_signed = false, + .value = .{ .uint32 = switch (lane_index) { + inline 0...2 => |idx| lanes[idx], + else => return RuntimeError.OutOfBounds, + } }, + } }, + .Vector4u32 => |lanes| return .{ .Int = .{ + .bit_count = 32, + .is_signed = false, + .value = .{ .uint32 = switch (lane_index) { + inline 0...3 => |idx| lanes[idx], + else => return RuntimeError.OutOfBounds, + } }, + } }, else => return RuntimeError.InvalidSpirV, }; @@ -2710,97 +2719,97 @@ fn opVectorShuffle(allocator: std.mem.Allocator, _: SpvWord, rt: *Runtime) Runti lanes[lane_index] = lane_value; }, - .Vector2f32 => |*lanes| { - if (lane_index >= 2) return RuntimeError.InvalidSpirV; - switch (lane_value) { - .Float => |f| { - if (f.bit_count != 32) return RuntimeError.InvalidSpirV; - lanes[lane_index] = f.value.float32; - }, - else => return RuntimeError.InvalidSpirV, - } + .Vector2f32 => |*lanes| switch (lane_value) { + .Float => |f| { + if (f.bit_count != 32) return RuntimeError.InvalidSpirV; + switch (lane_index) { + inline 0...1 => |i| lanes[i] = f.value.float32, + else => return RuntimeError.InvalidSpirV, + } + }, + else => return RuntimeError.InvalidSpirV, }, - .Vector3f32 => |*lanes| { - if (lane_index >= 3) return RuntimeError.InvalidSpirV; - switch (lane_value) { - .Float => |f| { - if (f.bit_count != 32) return RuntimeError.InvalidSpirV; - lanes[lane_index] = f.value.float32; - }, - else => return RuntimeError.InvalidSpirV, - } + .Vector3f32 => |*lanes| switch (lane_value) { + .Float => |f| { + if (f.bit_count != 32) return RuntimeError.InvalidSpirV; + switch (lane_index) { + inline 0...2 => |i| lanes[i] = f.value.float32, + else => return RuntimeError.InvalidSpirV, + } + }, + else => return RuntimeError.InvalidSpirV, }, - .Vector4f32 => |*lanes| { - if (lane_index >= 4) return RuntimeError.InvalidSpirV; - switch (lane_value) { - .Float => |f| { - if (f.bit_count != 32) return RuntimeError.InvalidSpirV; - lanes[lane_index] = f.value.float32; - }, - else => return RuntimeError.InvalidSpirV, - } + .Vector4f32 => |*lanes| switch (lane_value) { + .Float => |f| { + if (f.bit_count != 32) return RuntimeError.InvalidSpirV; + switch (lane_index) { + inline 0...3 => |i| lanes[i] = f.value.float32, + else => return RuntimeError.InvalidSpirV, + } + }, + else => return RuntimeError.InvalidSpirV, }, - .Vector2i32 => |*lanes| { - if (lane_index >= 2) return RuntimeError.InvalidSpirV; - switch (lane_value) { - .Int => |i| { - if (i.bit_count != 32) return RuntimeError.InvalidSpirV; - lanes[lane_index] = i.value.sint32; - }, - else => return RuntimeError.InvalidSpirV, - } + .Vector2i32 => |*lanes| switch (lane_value) { + .Int => |i| { + if (i.bit_count != 32) return RuntimeError.InvalidSpirV; + switch (lane_index) { + inline 0...1 => |idx| lanes[idx] = i.value.sint32, + else => return RuntimeError.InvalidSpirV, + } + }, + else => return RuntimeError.InvalidSpirV, }, - .Vector3i32 => |*lanes| { - if (lane_index >= 3) return RuntimeError.InvalidSpirV; - switch (lane_value) { - .Int => |i| { - if (i.bit_count != 32) return RuntimeError.InvalidSpirV; - lanes[lane_index] = i.value.sint32; - }, - else => return RuntimeError.InvalidSpirV, - } + .Vector3i32 => |*lanes| switch (lane_value) { + .Int => |i| { + if (i.bit_count != 32) return RuntimeError.InvalidSpirV; + switch (lane_index) { + inline 0...2 => |idx| lanes[idx] = i.value.sint32, + else => return RuntimeError.InvalidSpirV, + } + }, + else => return RuntimeError.InvalidSpirV, }, - .Vector4i32 => |*lanes| { - if (lane_index >= 4) return RuntimeError.InvalidSpirV; - switch (lane_value) { - .Int => |i| { - if (i.bit_count != 32) return RuntimeError.InvalidSpirV; - lanes[lane_index] = i.value.sint32; - }, - else => return RuntimeError.InvalidSpirV, - } + .Vector4i32 => |*lanes| switch (lane_value) { + .Int => |i| { + if (i.bit_count != 32) return RuntimeError.InvalidSpirV; + switch (lane_index) { + inline 0...3 => |idx| lanes[idx] = i.value.sint32, + else => return RuntimeError.InvalidSpirV, + } + }, + else => return RuntimeError.InvalidSpirV, }, - .Vector2u32 => |*lanes| { - if (lane_index >= 2) return RuntimeError.InvalidSpirV; - switch (lane_value) { - .Int => |i| { - if (i.bit_count != 32) return RuntimeError.InvalidSpirV; - lanes[lane_index] = i.value.uint32; - }, - else => return RuntimeError.InvalidSpirV, - } + .Vector2u32 => |*lanes| switch (lane_value) { + .Int => |i| { + if (i.bit_count != 32) return RuntimeError.InvalidSpirV; + switch (lane_index) { + inline 0...1 => |idx| lanes[idx] = i.value.uint32, + else => return RuntimeError.InvalidSpirV, + } + }, + else => return RuntimeError.InvalidSpirV, }, - .Vector3u32 => |*lanes| { - if (lane_index >= 3) return RuntimeError.InvalidSpirV; - switch (lane_value) { - .Int => |i| { - if (i.bit_count != 32) return RuntimeError.InvalidSpirV; - lanes[lane_index] = i.value.uint32; - }, - else => return RuntimeError.InvalidSpirV, - } + .Vector3u32 => |*lanes| switch (lane_value) { + .Int => |i| { + if (i.bit_count != 32) return RuntimeError.InvalidSpirV; + switch (lane_index) { + inline 0...2 => |idx| lanes[idx] = i.value.uint32, + else => return RuntimeError.InvalidSpirV, + } + }, + else => return RuntimeError.InvalidSpirV, }, - .Vector4u32 => |*lanes| { - if (lane_index >= 4) return RuntimeError.InvalidSpirV; - switch (lane_value) { - .Int => |i| { - if (i.bit_count != 32) return RuntimeError.InvalidSpirV; - lanes[lane_index] = i.value.uint32; - }, - else => return RuntimeError.InvalidSpirV, - } + .Vector4u32 => |*lanes| switch (lane_value) { + .Int => |i| { + if (i.bit_count != 32) return RuntimeError.InvalidSpirV; + switch (lane_index) { + inline 0...3 => |idx| lanes[idx] = i.value.uint32, + else => return RuntimeError.InvalidSpirV, + } + }, + else => return RuntimeError.InvalidSpirV, }, else => return RuntimeError.InvalidSpirV, diff --git a/test/bitwise.zig b/test/bitwise.zig index f88756d..076123b 100644 --- a/test/bitwise.zig +++ b/test/bitwise.zig @@ -101,7 +101,7 @@ test "Bitwise vectors" { inline for (types) |T| { const op1: case.Vec(L, T) = .{ .val = case.random(@Vector(L, T)) }; var op2: case.Vec(L, T) = .{ .val = case.random(@Vector(L, T)) }; - for (0..L) |i| op2.val[i] = @mod(op2.val[i], @bitSizeOf(T)); + inline for (0..L) |i| op2.val[i] = @mod(op2.val[i], @bitSizeOf(T)); const expected = switch (op.key) { .BitwiseAnd => op1.val & op2.val, .BitwiseOr => op1.val | op2.val, diff --git a/test/root.zig b/test/root.zig index 70b7d0c..4f26fa4 100644 --- a/test/root.zig +++ b/test/root.zig @@ -78,7 +78,7 @@ pub const case = struct { } pub fn random(comptime T: type) T { - var prng: std.Random.DefaultPrng = .init(@intCast(std.time.microTimestamp())); + var prng: std.Random.DefaultPrng = .init(@intCast(std.Io.Timestamp.now(std.testing.io, .real).toMicroseconds())); const rand = prng.random(); return switch (@typeInfo(T)) { @@ -86,7 +86,7 @@ pub const case = struct { .float => rand.float(T), .vector => |v| blk: { var vec: @Vector(v.len, v.child) = undefined; - for (0..v.len) |i| { + inline for (0..v.len) |i| { vec[i] = random(v.child); } break :blk vec; diff --git a/test/test_runner.zig b/test/test_runner.zig index 1f9af04..3fbdb2f 100644 --- a/test/test_runner.zig +++ b/test/test_runner.zig @@ -16,11 +16,8 @@ pub fn main() !void { const allocator = fba.allocator(); - const env = Env.init(allocator); - defer env.deinit(allocator); - var slowest = SlowTracker.init(allocator, 5); - defer slowest.deinit(); + defer slowest.deinit(allocator); var pass: usize = 0; var fail: usize = 0; @@ -46,13 +43,6 @@ pub fn main() !void { var status = Status.pass; slowest.startTiming(); - const is_unnamed_test = isUnnamed(t); - if (env.filter) |f| { - if (!is_unnamed_test and std.mem.indexOf(u8, t.name, f) == null) { - continue; - } - } - const friendly_name = blk: { const name = t.name; var it = std.mem.splitScalar(u8, name, '.'); @@ -70,7 +60,7 @@ pub fn main() !void { const result = t.func(); current_test = null; - const ns_taken = slowest.endTiming(friendly_name); + const ns_taken = slowest.endTiming(allocator, friendly_name); if (std.testing.allocator_instance.deinit() == .leak) { leak += 1; @@ -89,20 +79,13 @@ pub fn main() !void { fail += 1; Printer.status(.fail, "\n{s}\n\"{s}\" - {s}\n{s}\n", .{ BORDER, friendly_name, @errorName(err), BORDER }); if (@errorReturnTrace()) |trace| { - std.debug.dumpStackTrace(trace.*); - } - if (env.fail_first) { - break; + std.debug.dumpErrorReturnTrace(trace); } }, } - if (env.verbose) { - const ms = @as(f64, @floatFromInt(ns_taken)) / 1_000_000.0; - Printer.status(status, "\x1b[35m[{d: >10.2} ms]\x1b[0m {s: <30}", .{ ms, friendly_name }); - } else { - Printer.status(status, ".", .{}); - } + const ms = @as(f64, @floatFromInt(ns_taken)) / 1_000_000.0; + Printer.status(status, "\x1b[35m[{d: >10.2} ms]\x1b[0m {s: <30}", .{ ms, friendly_name }); } for (builtin.test_functions) |t| { @@ -126,7 +109,7 @@ pub fn main() !void { Printer.fmt("\n", .{}); try slowest.display(); Printer.fmt("\n", .{}); - std.posix.exit(if (fail == 0) 0 else 1); + std.process.exit(if (fail == 0) 0 else 1); } const Printer = struct { @@ -155,42 +138,41 @@ const SlowTracker = struct { const SlowestQueue = std.PriorityDequeue(TestInfo, void, compareTiming); max: usize, slowest: SlowestQueue, - timer: std.time.Timer, + timer: std.Io.Timestamp, fn init(allocator: Allocator, count: u32) SlowTracker { - const timer = std.time.Timer.start() catch @panic("failed to start timer"); - var slowest = SlowestQueue.init(allocator, {}); - slowest.ensureTotalCapacity(count) catch @panic("OOM"); + var slowest = SlowestQueue.empty; + slowest.ensureTotalCapacity(allocator, count) catch @panic("OOM"); return .{ .max = count, - .timer = timer, + .timer = std.Io.Timestamp.now(std.testing.io, .real), .slowest = slowest, }; } const TestInfo = struct { - ns: u64, + ns: i96, name: []const u8, }; - fn deinit(self: SlowTracker) void { - self.slowest.deinit(); + fn deinit(self: *SlowTracker, allocator: std.mem.Allocator) void { + self.slowest.deinit(allocator); } fn startTiming(self: *SlowTracker) void { - self.timer.reset(); + self.timer = std.Io.Timestamp.now(std.testing.io, .real); } - fn endTiming(self: *SlowTracker, test_name: []const u8) u64 { - var timer = self.timer; - const ns = timer.lap(); + fn endTiming(self: *SlowTracker, allocator: std.mem.Allocator, test_name: []const u8) i96 { + const duration = self.timer.untilNow(std.testing.io, .real); + const ns = duration.toNanoseconds(); var slowest = &self.slowest; if (slowest.count() < self.max) { // Capacity is fixed to the # of slow tests we want to track // If we've tracked fewer tests than this capacity, than always add - slowest.add(TestInfo{ .ns = ns, .name = test_name }) catch @panic("failed to track test timing"); + slowest.push(allocator, TestInfo{ .ns = ns, .name = test_name }) catch @panic("failed to track test timing"); return ns; } @@ -205,8 +187,8 @@ const SlowTracker = struct { } // the previous fastest of our slow tests, has been pushed off. - _ = slowest.removeMin(); - slowest.add(TestInfo{ .ns = ns, .name = test_name }) catch @panic("failed to track test timing"); + _ = slowest.popMin(); + slowest.push(allocator, TestInfo{ .ns = ns, .name = test_name }) catch @panic("failed to track test timing"); return ns; } @@ -214,7 +196,7 @@ const SlowTracker = struct { var slowest = self.slowest; const count = slowest.count(); Printer.fmt("Slowest {d} test{s}: \n", .{ count, if (count != 1) "s" else "" }); - while (slowest.removeMinOrNull()) |info| { + while (slowest.popMin()) |info| { const ms = @as(f64, @floatFromInt(info.ns)) / 1_000_000.0; Printer.fmt(" {d:.2}ms\t{s}\n", .{ ms, info.name }); } @@ -226,43 +208,6 @@ const SlowTracker = struct { } }; -const Env = struct { - verbose: bool, - fail_first: bool, - filter: ?[]const u8, - - fn init(allocator: Allocator) Env { - return .{ - .verbose = readEnvBool(allocator, "TEST_VERBOSE", true), - .fail_first = readEnvBool(allocator, "TEST_FAIL_FIRST", false), - .filter = readEnv(allocator, "TEST_FILTER"), - }; - } - - fn deinit(self: Env, allocator: Allocator) void { - if (self.filter) |f| { - allocator.free(f); - } - } - - fn readEnv(allocator: Allocator, key: []const u8) ?[]const u8 { - const v = std.process.getEnvVarOwned(allocator, key) catch |err| { - if (err == error.EnvironmentVariableNotFound) { - return null; - } - std.log.warn("failed to get env var {s} due to err {}", .{ key, err }); - return null; - }; - return v; - } - - fn readEnvBool(allocator: Allocator, key: []const u8, deflt: bool) bool { - const value = readEnv(allocator, key) orelse return deflt; - defer allocator.free(value); - return std.ascii.eqlIgnoreCase(value, "true"); - } -}; - pub const panic = std.debug.FullPanic(struct { pub fn panicFn(msg: []const u8, first_trace_addr: ?usize) noreturn { if (current_test) |ct| {