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, "x11", self.x11);
|
||||||
step.addOption(bool, "wayland", self.wayland);
|
step.addOption(bool, "wayland", self.wayland);
|
||||||
step.addOption(bool, "sentry", self.sentry);
|
step.addOption(bool, "sentry", self.sentry);
|
||||||
|
step.addOption(bool, "simd", self.simd);
|
||||||
step.addOption(bool, "i18n", self.i18n);
|
step.addOption(bool, "i18n", self.i18n);
|
||||||
step.addOption(ApprtRuntime, "app_runtime", self.app_runtime);
|
step.addOption(ApprtRuntime, "app_runtime", self.app_runtime);
|
||||||
step.addOption(FontBackend, "font_backend", self.font_backend);
|
step.addOption(FontBackend, "font_backend", self.font_backend);
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,7 @@ pub fn add(
|
||||||
const vt_options = @import("../terminal/build_options.zig");
|
const vt_options = @import("../terminal/build_options.zig");
|
||||||
vt_options.addOptions(b, step.root_module, .{
|
vt_options.addOptions(b, step.root_module, .{
|
||||||
.artifact = .ghostty,
|
.artifact = .ghostty,
|
||||||
|
.simd = self.config.simd,
|
||||||
.slow_runtime_safety = switch (optimize) {
|
.slow_runtime_safety = switch (optimize) {
|
||||||
.Debug => true,
|
.Debug => true,
|
||||||
.ReleaseSafe,
|
.ReleaseSafe,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,63 @@
|
||||||
const std = @import("std");
|
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
|
// base64.cpp
|
||||||
extern "c" fn ghostty_simd_base64_max_length(
|
extern "c" fn ghostty_simd_base64_max_length(
|
||||||
|
|
@ -11,16 +70,6 @@ extern "c" fn ghostty_simd_base64_decode(
|
||||||
output: [*]u8,
|
output: [*]u8,
|
||||||
) isize;
|
) 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" {
|
test "base64 maxLen" {
|
||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const len = maxLen("aGVsbG8gd29ybGQ=");
|
const len = maxLen("aGVsbG8gd29ybGQ=");
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const options = @import("build_options");
|
||||||
|
|
||||||
// vt.cpp
|
// vt.cpp
|
||||||
extern "c" fn ghostty_simd_codepoint_width(u32) i8;
|
extern "c" fn ghostty_simd_codepoint_width(u32) i8;
|
||||||
|
|
||||||
pub fn codepointWidth(cp: u32) i8 {
|
pub fn codepointWidth(cp: u32) i8 {
|
||||||
//return @import("ziglyph").display_width.codePointWidth(@intCast(cp), .half);
|
if (comptime options.simd) return ghostty_simd_codepoint_width(cp);
|
||||||
return ghostty_simd_codepoint_width(cp);
|
return @import("ziglyph").display_width.codePointWidth(@intCast(cp), .half);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "codepointWidth basic" {
|
test "codepointWidth basic" {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
|
const options = @import("build_options");
|
||||||
|
|
||||||
extern "c" fn ghostty_simd_index_of(
|
extern "c" fn ghostty_simd_index_of(
|
||||||
needle: u8,
|
needle: u8,
|
||||||
|
|
@ -8,8 +9,16 @@ extern "c" fn ghostty_simd_index_of(
|
||||||
) usize;
|
) usize;
|
||||||
|
|
||||||
pub fn indexOf(input: []const u8, needle: u8) ?usize {
|
pub fn indexOf(input: []const u8, needle: u8) ?usize {
|
||||||
const result = ghostty_simd_index_of(needle, input.ptr, input.len);
|
if (comptime options.simd) {
|
||||||
return if (result == input.len) null else result;
|
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" {
|
test "indexOf" {
|
||||||
|
|
|
||||||
|
|
@ -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 std = @import("std");
|
||||||
|
|
||||||
const codepoint_width = @import("codepoint_width.zig");
|
const codepoint_width = @import("codepoint_width.zig");
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const options = @import("build_options");
|
||||||
|
const assert = std.debug.assert;
|
||||||
|
const indexOf = @import("index_of.zig").indexOf;
|
||||||
|
|
||||||
// vt.cpp
|
// vt.cpp
|
||||||
extern "c" fn ghostty_simd_decode_utf8_until_control_seq(
|
extern "c" fn ghostty_simd_decode_utf8_until_control_seq(
|
||||||
|
|
@ -17,15 +20,43 @@ pub fn utf8DecodeUntilControlSeq(
|
||||||
input: []const u8,
|
input: []const u8,
|
||||||
output: []u32,
|
output: []u32,
|
||||||
) DecodeResult {
|
) DecodeResult {
|
||||||
var decoded: usize = 0;
|
assert(output.len >= input.len);
|
||||||
const consumed = ghostty_simd_decode_utf8_until_control_seq(
|
|
||||||
input.ptr,
|
|
||||||
input.len,
|
|
||||||
output.ptr,
|
|
||||||
&decoded,
|
|
||||||
);
|
|
||||||
|
|
||||||
return .{ .consumed = consumed, .decoded = decoded };
|
if (comptime options.simd) {
|
||||||
|
var decoded: usize = 0;
|
||||||
|
const consumed = ghostty_simd_decode_utf8_until_control_seq(
|
||||||
|
input.ptr,
|
||||||
|
input.len,
|
||||||
|
output.ptr,
|
||||||
|
&decoded,
|
||||||
|
);
|
||||||
|
|
||||||
|
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" {
|
test "decode no escape" {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue