simd: add scalar fallbacks to all for build_options.simd false
parent
8aa4373aaf
commit
6893024c51
|
|
@ -460,6 +460,7 @@ pub fn addOptions(self: *const Config, step: *std.Build.Step.Options) !void {
|
|||
step.addOption(bool, "x11", self.x11);
|
||||
step.addOption(bool, "wayland", self.wayland);
|
||||
step.addOption(bool, "sentry", self.sentry);
|
||||
step.addOption(bool, "simd", self.simd);
|
||||
step.addOption(bool, "i18n", self.i18n);
|
||||
step.addOption(ApprtRuntime, "app_runtime", self.app_runtime);
|
||||
step.addOption(FontBackend, "font_backend", self.font_backend);
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ pub fn add(
|
|||
const vt_options = @import("../terminal/build_options.zig");
|
||||
vt_options.addOptions(b, step.root_module, .{
|
||||
.artifact = .ghostty,
|
||||
.simd = self.config.simd,
|
||||
.slow_runtime_safety = switch (optimize) {
|
||||
.Debug => true,
|
||||
.ReleaseSafe,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,63 @@
|
|||
const std = @import("std");
|
||||
const options = @import("build_options");
|
||||
const assert = std.debug.assert;
|
||||
const log = std.log.scoped(.simd_base64);
|
||||
|
||||
// Used for the non-SIMD implementation
|
||||
const Base64Decoder = std.base64.standard_no_pad.Decoder;
|
||||
|
||||
pub fn maxLen(input: []const u8) usize {
|
||||
if (comptime options.simd) return ghostty_simd_base64_max_length(
|
||||
input.ptr,
|
||||
input.len,
|
||||
);
|
||||
|
||||
return maxLenScalar(input);
|
||||
}
|
||||
|
||||
fn maxLenScalar(input: []const u8) usize {
|
||||
return Base64Decoder.calcSizeForSlice(scalarInput(input)) catch |err| {
|
||||
log.warn("failed to calculate base64 size for payload: {}", .{err});
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
pub fn decode(input: []const u8, output: []u8) error{Base64Invalid}![]const u8 {
|
||||
if (comptime options.simd) {
|
||||
const res = ghostty_simd_base64_decode(
|
||||
input.ptr,
|
||||
input.len,
|
||||
output.ptr,
|
||||
);
|
||||
if (res < 0) return error.Base64Invalid;
|
||||
return output[0..@intCast(res)];
|
||||
}
|
||||
|
||||
return decodeScalar(input, output);
|
||||
}
|
||||
|
||||
fn decodeScalar(
|
||||
input_raw: []const u8,
|
||||
output: []u8,
|
||||
) error{Base64Invalid}![]const u8 {
|
||||
const input = scalarInput(input_raw);
|
||||
const size = maxLenScalar(input);
|
||||
if (size == 0) return "";
|
||||
assert(output.len >= size);
|
||||
Base64Decoder.decode(
|
||||
output,
|
||||
scalarInput(input),
|
||||
) catch return error.Base64Invalid;
|
||||
return output[0..size];
|
||||
}
|
||||
|
||||
/// For non-SIMD enabled builds, we trim the padding from the end of the
|
||||
/// base64 input in order to get identical output with the SIMD version.
|
||||
fn scalarInput(input: []const u8) []const u8 {
|
||||
var i: usize = 0;
|
||||
while (input[input.len - i - 1] == '=') i += 1;
|
||||
return input[0 .. input.len - i];
|
||||
}
|
||||
|
||||
// base64.cpp
|
||||
extern "c" fn ghostty_simd_base64_max_length(
|
||||
|
|
@ -11,16 +70,6 @@ extern "c" fn ghostty_simd_base64_decode(
|
|||
output: [*]u8,
|
||||
) isize;
|
||||
|
||||
pub fn maxLen(input: []const u8) usize {
|
||||
return ghostty_simd_base64_max_length(input.ptr, input.len);
|
||||
}
|
||||
|
||||
pub fn decode(input: []const u8, output: []u8) error{Base64Invalid}![]const u8 {
|
||||
const res = ghostty_simd_base64_decode(input.ptr, input.len, output.ptr);
|
||||
if (res < 0) return error.Base64Invalid;
|
||||
return output[0..@intCast(res)];
|
||||
}
|
||||
|
||||
test "base64 maxLen" {
|
||||
const testing = std.testing;
|
||||
const len = maxLen("aGVsbG8gd29ybGQ=");
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
const std = @import("std");
|
||||
const options = @import("build_options");
|
||||
|
||||
// vt.cpp
|
||||
extern "c" fn ghostty_simd_codepoint_width(u32) i8;
|
||||
|
||||
pub fn codepointWidth(cp: u32) i8 {
|
||||
//return @import("ziglyph").display_width.codePointWidth(@intCast(cp), .half);
|
||||
return ghostty_simd_codepoint_width(cp);
|
||||
if (comptime options.simd) return ghostty_simd_codepoint_width(cp);
|
||||
return @import("ziglyph").display_width.codePointWidth(@intCast(cp), .half);
|
||||
}
|
||||
|
||||
test "codepointWidth basic" {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const options = @import("build_options");
|
||||
|
||||
extern "c" fn ghostty_simd_index_of(
|
||||
needle: u8,
|
||||
|
|
@ -8,10 +9,18 @@ extern "c" fn ghostty_simd_index_of(
|
|||
) usize;
|
||||
|
||||
pub fn indexOf(input: []const u8, needle: u8) ?usize {
|
||||
if (comptime options.simd) {
|
||||
const result = ghostty_simd_index_of(needle, input.ptr, input.len);
|
||||
return if (result == input.len) null else result;
|
||||
}
|
||||
|
||||
return indexOfScalar(input, needle);
|
||||
}
|
||||
|
||||
fn indexOfScalar(input: []const u8, needle: u8) ?usize {
|
||||
return std.mem.indexOfScalar(u8, input, needle);
|
||||
}
|
||||
|
||||
test "indexOf" {
|
||||
const testing = std.testing;
|
||||
try testing.expect(indexOf("hello", ' ') == null);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
//! SIMD-optimized routines. If `build_options.simd` is false, then the API
|
||||
//! still works but we fall back to pure Zig scalar implementations.
|
||||
|
||||
const std = @import("std");
|
||||
|
||||
const codepoint_width = @import("codepoint_width.zig");
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
const std = @import("std");
|
||||
const options = @import("build_options");
|
||||
const assert = std.debug.assert;
|
||||
const indexOf = @import("index_of.zig").indexOf;
|
||||
|
||||
// vt.cpp
|
||||
extern "c" fn ghostty_simd_decode_utf8_until_control_seq(
|
||||
|
|
@ -17,6 +20,9 @@ pub fn utf8DecodeUntilControlSeq(
|
|||
input: []const u8,
|
||||
output: []u32,
|
||||
) DecodeResult {
|
||||
assert(output.len >= input.len);
|
||||
|
||||
if (comptime options.simd) {
|
||||
var decoded: usize = 0;
|
||||
const consumed = ghostty_simd_decode_utf8_until_control_seq(
|
||||
input.ptr,
|
||||
|
|
@ -28,6 +34,31 @@ pub fn utf8DecodeUntilControlSeq(
|
|||
return .{ .consumed = consumed, .decoded = decoded };
|
||||
}
|
||||
|
||||
return utf8DecodeUntilControlSeqScalar(input, output);
|
||||
}
|
||||
|
||||
fn utf8DecodeUntilControlSeqScalar(
|
||||
input: []const u8,
|
||||
output: []u32,
|
||||
) DecodeResult {
|
||||
// Find our escape
|
||||
const idx = indexOf(input, 0x1B) orelse input.len;
|
||||
|
||||
// Copy up to the escape
|
||||
const view = std.unicode.Utf8View.init(input[0..idx]) catch unreachable;
|
||||
var it = view.iterator();
|
||||
var i: usize = 0;
|
||||
while (it.nextCodepoint()) |cp| {
|
||||
output[i] = @intCast(cp);
|
||||
i += 1;
|
||||
}
|
||||
|
||||
return .{
|
||||
.consumed = idx,
|
||||
.decoded = i,
|
||||
};
|
||||
}
|
||||
|
||||
test "decode no escape" {
|
||||
const testing = std.testing;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue