diff --git a/mojo/Makefile b/mojo/Makefile new file mode 100644 index 0000000000..c8648a298b --- /dev/null +++ b/mojo/Makefile @@ -0,0 +1,17 @@ +MOJO = pixi run mojo +PLUGIN_DIR = /usr/lib/darktable/plugins + +.PHONY: all build install bench clean + +all: build + +build: libsigmoid_mojo.so + +libsigmoid_mojo.so: iop/sigmoid/lib.mojo iop/sigmoid/kernels.mojo + $(MOJO) build -I . iop/sigmoid/lib.mojo --emit shared-lib -o libsigmoid_mojo.so + +install: libsigmoid_mojo.so + sudo cp libsigmoid_mojo.so $(PLUGIN_DIR)/ + +clean: + rm -f libsigmoid_mojo.so diff --git a/mojo/build_sigmoid_iop.sh b/mojo/build_sigmoid_iop.sh new file mode 100755 index 0000000000..0c06170049 --- /dev/null +++ b/mojo/build_sigmoid_iop.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# Build libsigmoid.so from the darktable source tree. +# This mimics what CMake does (run introspection, then compile + link). + +set -e + +SRC=/home/mc/code/darktable +BUILD=/tmp/sigmoid_build +DEST=$BUILD/libsigmoid.so + +mkdir -p "$BUILD" + +# Step 1: Run introspection (generates introspection_sigmoid.c) +echo "=== Step 1: Introspection ===" +perl "$SRC/tools/introspection/parser.pl" \ + "$SRC/src/" \ + "$SRC/src/iop/sigmoid.c" \ + "$BUILD/introspection_sigmoid.c" +echo " -> $BUILD/introspection_sigmoid.c ($(wc -l < "$BUILD/introspection_sigmoid.c") lines)" + +# Step 2: Collect flags +GTK_FLAGS=$(pkg-config --cflags gtk+-3.0 glib-2.0 librsvg-2.0 lcms2 json-glib-1.0) +DT_INCLUDE="-I$SRC/src -I$SRC/src/iop -I$SRC/build/bin -I/usr/lib/darktable" +DEFINES="-DHAVE_CONFIG_H -DHAVE_OPENCL -D_GNU_SOURCE -include common/module_api.h -include iop/iop_api.h" +CFLAGS="-O3 -march=native -fPIC -fvisibility=hidden -fopenmp $GTK_FLAGS $DT_INCLUDE $DEFINES" +LDFLAGS="-L/usr/lib/darktable -ldarktable -lm -lgomp -Wl,-rpath,/usr/lib/darktable" + +echo "" +echo "=== Step 2: Compile ===" +gcc $CFLAGS \ + -Wno-unused-function \ + -Wno-deprecated-declarations \ + -c "$BUILD/introspection_sigmoid.c" \ + -o "$BUILD/introspection_sigmoid.o" 2>&1 +echo " -> $BUILD/introspection_sigmoid.o" + +echo "" +echo "=== Step 3: Link ===" +gcc -shared -fPIC -fopenmp \ + "$BUILD/introspection_sigmoid.o" \ + $LDFLAGS \ + -o "$DEST" +echo " -> $DEST" + +echo "" +echo "=== Step 4: Verify ===" +nm -D "$DEST" | grep " T " | awk '{print $3}' + +echo "" +echo "Build complete: $DEST" +echo "Size: $(du -sh "$DEST" | cut -f1)" diff --git a/mojo/iop/__init__.mojo b/mojo/iop/__init__.mojo new file mode 100644 index 0000000000..0c393fc1b4 --- /dev/null +++ b/mojo/iop/__init__.mojo @@ -0,0 +1 @@ +# iop package diff --git a/mojo/iop/sigmoid/__init__.mojo b/mojo/iop/sigmoid/__init__.mojo new file mode 100644 index 0000000000..256cd8163f --- /dev/null +++ b/mojo/iop/sigmoid/__init__.mojo @@ -0,0 +1 @@ +# iop.sigmoid package diff --git a/mojo/iop/sigmoid/kernels.mojo b/mojo/iop/sigmoid/kernels.mojo new file mode 100644 index 0000000000..c5b1a3d220 --- /dev/null +++ b/mojo/iop/sigmoid/kernels.mojo @@ -0,0 +1,281 @@ +from std.math import isnan, sqrt, pow, max, min + +@always_inline +fn generalized_loglogistic_sigmoid_scalar( + value: Float32, + magnitude: Float32, + paper_exp: Float32, + film_fog: Float32, + film_power: Float32, + paper_power: Float32, +) -> Float32: + var clamped_value = max(value, Float32(0.0)) + var film_response = pow(film_fog + clamped_value, film_power) + var paper_response = magnitude * pow( + film_response / (paper_exp + film_response), paper_power + ) + if isnan(paper_response): + return magnitude + return paper_response + +@always_inline +fn apply_sigmoid_rgb_ratio( + in_r: Float32, + in_g: Float32, + in_b: Float32, + in_a: Float32, + white_target: Float32, + black_target: Float32, + paper_exp: Float32, + film_fog: Float32, + film_power: Float32, + paper_power: Float32, +) -> SIMD[DType.float32, 4]: + # Desaturate negative values + var avg = max((in_r + in_g + in_b) / 3.0, Float32(0.0)) + var min_v = min(min(in_r, in_g), in_b) + var sat = Float32(1.0) + if min_v < 0.0: + sat = -avg / (min_v - avg) + + var p_r = avg + sat * (in_r - avg) + var p_g = avg + sat * (in_g - avg) + var p_b = avg + sat * (in_b - avg) + + var luma = (p_r + p_g + p_b) / 3.0 + var mapped_luma = generalized_loglogistic_sigmoid_scalar( + luma, white_target, paper_exp, film_fog, film_power, paper_power + ) + + if luma > 1e-9: + var scale = mapped_luma / luma + p_r *= scale + p_g *= scale + p_b *= scale + else: + p_r = mapped_luma + p_g = mapped_luma + p_b = mapped_luma + + var p_min = min(min(p_r, p_g), p_b) + var p_max = max(max(p_r, p_g), p_b) + var eps = Float32(1e-6) + var d_white = (white_target - mapped_luma) / (p_max - mapped_luma + eps) + var d_black = (black_target - mapped_luma) / (p_min - mapped_luma - eps) + var db_vs_chroma = min(d_white, d_black) + var cvm_border = (mapped_luma - p_min) / (mapped_luma + eps) + var p_chr_adj = 1.0 / (cvm_border * db_vs_chroma + eps) + var h_chr = ( + 2.0 * cvm_border / (1.0 - cvm_border * cvm_border + eps) + ) * p_chr_adj + var h_z = sqrt(h_chr * h_chr + 1.0) + var chroma_f = h_chr / (1.0 + h_z) * db_vs_chroma + + return SIMD[DType.float32, 4]( + mapped_luma + chroma_f * (p_r - mapped_luma), + mapped_luma + chroma_f * (p_g - mapped_luma), + mapped_luma + chroma_f * (p_b - mapped_luma), + in_a, + ) + +@always_inline +fn apply_sigmoid_per_channel( + in_r: Float32, + in_g: Float32, + in_b: Float32, + in_a: Float32, + white_target: Float32, + paper_exp: Float32, + film_fog: Float32, + contrast_power: Float32, + skew_power: Float32, + hue_preservation: Float32, + pipe_to_base: SIMD[DType.float32, 16], + base_to_rendering: SIMD[DType.float32, 16], + rendering_to_pipe: SIMD[DType.float32, 16], +) -> SIMD[DType.float32, 4]: + # 1. Transform to base space + var i_r = ( + pipe_to_base[0] * in_r + pipe_to_base[1] * in_g + pipe_to_base[2] * in_b + ) + var i_g = ( + pipe_to_base[4] * in_r + pipe_to_base[5] * in_g + pipe_to_base[6] * in_b + ) + var i_b = ( + pipe_to_base[8] * in_r + + pipe_to_base[9] * in_g + + pipe_to_base[10] * in_b + ) + + # 2. Desaturate negative + var avg = max((i_r + i_g + i_b) / 3.0, Float32(0.0)) + var min_v = min(min(i_r, i_g), i_b) + var sat = Float32(1.0) + if min_v < 0.0: + sat = -avg / (min_v - avg) + i_r = avg + sat * (i_r - avg) + i_g = avg + sat * (i_g - avg) + i_b = avg + sat * (i_b - avg) + + # 3. Transform to rendering space + var r_r = ( + base_to_rendering[0] * i_r + + base_to_rendering[1] * i_g + + base_to_rendering[2] * i_b + ) + var r_g = ( + base_to_rendering[4] * i_r + + base_to_rendering[5] * i_g + + base_to_rendering[6] * i_b + ) + var r_b = ( + base_to_rendering[8] * i_r + + base_to_rendering[9] * i_g + + base_to_rendering[10] * i_b + ) + + # 4. Per-channel sigmoid curves + var pc_r = generalized_loglogistic_sigmoid_scalar( + r_r, white_target, paper_exp, film_fog, contrast_power, skew_power + ) + var pc_g = generalized_loglogistic_sigmoid_scalar( + r_g, white_target, paper_exp, film_fog, contrast_power, skew_power + ) + var pc_b = generalized_loglogistic_sigmoid_scalar( + r_b, white_target, paper_exp, film_fog, contrast_power, skew_power + ) + + # 5. Preserve hue & energy + var p_min: Float32 + var p_mid: Float32 + var p_max: Float32 + var pc_min: Float32 + var pc_mid: Float32 + var pc_max: Float32 + + if r_r >= r_g: + if r_g >= r_b: # R G B + p_max = r_r + p_mid = r_g + p_min = r_b + pc_max = pc_r + pc_mid = pc_g + pc_min = pc_b + elif r_b >= r_r: # B R G + p_max = r_b + p_mid = r_r + p_min = r_g + pc_max = pc_b + pc_mid = pc_r + pc_min = pc_g + else: # R B G + p_max = r_r + p_mid = r_b + p_min = r_g + pc_max = pc_r + pc_mid = pc_b + pc_min = pc_g + else: + if r_r >= r_b: # G R B + p_max = r_g + p_mid = r_r + p_min = r_b + pc_max = pc_g + pc_mid = pc_r + pc_min = pc_b + elif r_b >= r_g: # B G R + p_max = r_b + p_mid = r_g + p_min = r_r + pc_max = pc_b + pc_mid = pc_g + pc_min = pc_r + else: # G B R + p_max = r_g + p_mid = r_b + p_min = r_r + pc_max = pc_g + pc_mid = pc_b + pc_min = pc_r + + var chroma = p_max - p_min + var midscale = Float32(0.0) + if chroma != 0.0: + midscale = (p_mid - p_min) / chroma + + var f_hc = pc_min + (pc_max - pc_min) * midscale + var n_mid = (1.0 - hue_preservation) * pc_mid + hue_preservation * f_hc + + var blend = 2.0 * p_min / (p_min + p_mid + 1e-9) + var target = blend * (pc_r + pc_g + pc_b) + (1.0 - blend) * ( + pc_min + n_mid + pc_max + ) + + var res_min: Float32 + var res_mid: Float32 + var res_max: Float32 + if n_mid <= pc_mid: + res_mid = ( + (1.0 - hue_preservation) * pc_mid + + hue_preservation + * (midscale * pc_max + (1.0 - midscale) * (target - pc_max)) + ) / (1.0 + hue_preservation * (1.0 - midscale)) + res_min = target - pc_max - res_mid + res_max = pc_max + else: + res_mid = ( + (1.0 - hue_preservation) * pc_mid + + hue_preservation + * (pc_min * (1.0 - midscale) + midscale * (target - pc_min)) + ) / (1.0 + hue_preservation * midscale) + res_min = pc_min + res_max = target - pc_min - res_mid + + var res_r: Float32 + var res_g: Float32 + var res_b: Float32 + if r_r >= r_g: + if r_g >= r_b: # R G B + res_r = res_max + res_g = res_mid + res_b = res_min + elif r_b >= r_r: # B R G + res_b = res_max + res_r = res_mid + res_g = res_min + else: # R B G + res_r = res_max + res_b = res_mid + res_g = res_min + else: + if r_r >= r_b: # G R B + res_g = res_max + res_r = res_mid + res_b = res_min + elif r_b >= r_g: # B G R + res_b = res_max + res_g = res_mid + res_r = res_min + else: # G B R + res_g = res_max + res_b = res_mid + res_r = res_min + + # 6. Transform to pipe space + var out_r = ( + rendering_to_pipe[0] * res_r + + rendering_to_pipe[1] * res_g + + rendering_to_pipe[2] * res_b + ) + var out_g = ( + rendering_to_pipe[4] * res_r + + rendering_to_pipe[5] * res_g + + rendering_to_pipe[6] * res_b + ) + var out_b = ( + rendering_to_pipe[8] * res_r + + rendering_to_pipe[9] * res_g + + rendering_to_pipe[10] * res_b + ) + + return SIMD[DType.float32, 4](out_r, out_g, out_b, in_a) diff --git a/mojo/iop/sigmoid/lib.mojo b/mojo/iop/sigmoid/lib.mojo new file mode 100644 index 0000000000..e0bcb90375 --- /dev/null +++ b/mojo/iop/sigmoid/lib.mojo @@ -0,0 +1,370 @@ +from std.gpu.host import DeviceContext +from layout import Layout, LayoutTensor, UNKNOWN_VALUE +from layout.runtime_layout import RuntimeLayout +from std.utils import Index, IndexList +from std.algorithm.functional import elementwise +from std.gpu.host.compile import get_gpu_target +from std.memory.unsafe_pointer import alloc, UnsafePointer +from std.sys import simd_width_of +from iop.sigmoid.kernels import ( + apply_sigmoid_rgb_ratio, + apply_sigmoid_per_channel, +) + +comptime CHANNELS = 4 +comptime IMAGE_LAYOUT = Layout.row_major(UNKNOWN_VALUE, UNKNOWN_VALUE, CHANNELS) +comptime DTYPE = DType.float32 +comptime SIMD_WIDTH = simd_width_of[DTYPE, target=get_gpu_target()]() + + +struct MojoCtx: + var use_gpu: Int + var dctx_addr: Int + + fn __init__(out self, use_gpu: Int, dctx_addr: Int): + self.use_gpu = use_gpu + self.dctx_addr = dctx_addr + + +struct CParamsView: + var p: UnsafePointer[Float32, MutAnyOrigin] + + fn __init__(out self, p: Int): + self.p = UnsafePointer[Float32, MutAnyOrigin](unsafe_from_address=p) + + # In SigmoidMojoParams, each scalar is a float[4] array + fn white_target(self) -> Float32: + return self.p[0] + + fn black_target(self) -> Float32: + return self.p[4] + + fn paper_exposure(self) -> Float32: + return self.p[8] + + fn film_fog(self) -> Float32: + return self.p[12] + + fn film_power(self) -> Float32: + return self.p[16] + + fn paper_power(self) -> Float32: + return self.p[20] + + fn hue_preservation(self) -> Float32: + return self.p[32] # hue_preservation[4] at index 32 + + fn pipe_to_base(self) -> SIMD[DType.float32, 16]: + var m = SIMD[DType.float32, 16]() + for i in range(16): + m[i] = self.p[36 + i] + return m + + fn base_to_rendering(self) -> SIMD[DType.float32, 16]: + var m = SIMD[DType.float32, 16]() + for i in range(16): + m[i] = self.p[52 + i] + return m + + fn rendering_to_pipe(self) -> SIMD[DType.float32, 16]: + var m = SIMD[DType.float32, 16]() + for i in range(16): + m[i] = self.p[68 + i] + return m + + +# ========================================================================= +# INTERNAL GPU LAUNCHERS (ZERO-POINTER PARAMETERS) +# ========================================================================= + + +fn _launch_rgb_ratio_gpu( + dctx: DeviceContext, + dev_in_ptr: Int, + dev_out_ptr: Int, + wt: Float32, + bt: Float32, + pe: Float32, + ff: Float32, + fp: Float32, + pp: Float32, + num_pixels: Int, +) raises: + @parameter + @always_inline + fn gpu_kernel[ + sw: Int, rank: Int, align: Int + ](indices: IndexList[rank]) capturing -> None: + var idx = indices[0] * 4 + var pin = UnsafePointer[Float32, ImmutAnyOrigin]( + unsafe_from_address=dev_in_ptr + ) + var pout = UnsafePointer[Float32, MutAnyOrigin]( + unsafe_from_address=dev_out_ptr + ) + + var r = apply_sigmoid_rgb_ratio( + pin[idx], + pin[idx + 1], + pin[idx + 2], + pin[idx + 3], + wt, + bt, + pe, + ff, + fp, + pp, + ) + pout[idx] = r[0] + pout[idx + 1] = r[1] + pout[idx + 2] = r[2] + pout[idx + 3] = r[3] + + elementwise[gpu_kernel, SIMD_WIDTH, target="gpu"](num_pixels, dctx) + dctx.synchronize() + + +fn _launch_per_channel_gpu( + dctx: DeviceContext, + dev_in_ptr: Int, + dev_out_ptr: Int, + wt: Float32, + pe: Float32, + ff: Float32, + fp: Float32, + pp: Float32, + hp: Float32, + kptb: SIMD[DType.float32, 16], + kbtr: SIMD[DType.float32, 16], + krtp: SIMD[DType.float32, 16], + num_pixels: Int, +) raises: + @parameter + @always_inline + fn gpu_kernel[ + sw: Int, rank: Int, align: Int + ](indices: IndexList[rank]) capturing -> None: + var idx = indices[0] * 4 + var pin = UnsafePointer[Float32, ImmutAnyOrigin]( + unsafe_from_address=dev_in_ptr + ) + var pout = UnsafePointer[Float32, MutAnyOrigin]( + unsafe_from_address=dev_out_ptr + ) + + var r = apply_sigmoid_per_channel( + pin[idx], + pin[idx + 1], + pin[idx + 2], + pin[idx + 3], + wt, + pe, + ff, + fp, + pp, + hp, + kptb, + kbtr, + krtp, + ) + pout[idx] = r[0] + pout[idx + 1] = r[1] + pout[idx + 2] = r[2] + pout[idx + 3] = r[3] + + elementwise[gpu_kernel, SIMD_WIDTH, target="gpu"](num_pixels, dctx) + dctx.synchronize() + + +# ========================================================================= +# EXPORTED INTERFACE +# ========================================================================= + + +@export +fn sigmoid_mojo_init(ctx_out: UnsafePointer[Int, MutAnyOrigin], use_gpu: Int32): + var gpu = use_gpu != 0 + var dctx_addr = 0 + if gpu: + try: + var d_ptr = alloc[DeviceContext](1) + d_ptr.init_pointee_move(DeviceContext()) + dctx_addr = Int(d_ptr) + print("Mojo: GPU Context Initialized Successfully") + except e: + print("Mojo: GPU Init Error (falling back to CPU):", String(e)) + gpu = False + else: + print("Mojo: CPU Context Initialized") + var p = alloc[MojoCtx](1) + p[0].use_gpu = 1 if gpu else 0 + p[0].dctx_addr = dctx_addr + ctx_out[0] = Int(p) + + +@export +fn sigmoid_mojo_destroy(ctx_addr: Int): + var p = UnsafePointer[MojoCtx, MutAnyOrigin](unsafe_from_address=ctx_addr) + if p[0].dctx_addr != 0: + var dctx_ptr = UnsafePointer[DeviceContext, MutAnyOrigin]( + unsafe_from_address=p[0].dctx_addr + ) + dctx_ptr.destroy_pointee() + dctx_ptr.free() + p.free() + + +@export +fn sigmoid_mojo_rgb_ratio( + ctx_addr: Int, + in_addr: Int, + out_addr: Int, + width: Int32, + height: Int32, + p_addr: Int, +): + var ctx_p = UnsafePointer[MojoCtx, MutAnyOrigin]( + unsafe_from_address=ctx_addr + ) + var use_gpu = ctx_p[0].use_gpu != 0 + var dctx_addr = ctx_p[0].dctx_addr + var params = CParamsView(p_addr) + var in_p = UnsafePointer[Float32, MutAnyOrigin](unsafe_from_address=in_addr) + var out_p = UnsafePointer[Float32, MutAnyOrigin]( + unsafe_from_address=out_addr + ) + var h = Int(height) + var w = Int(width) + var num_pixels = h * w + + if use_gpu and dctx_addr != 0: + try: + var dctx = UnsafePointer[DeviceContext, MutAnyOrigin]( + unsafe_from_address=dctx_addr + )[0] + var dev_in = dctx.enqueue_create_buffer[DTYPE](num_pixels * 4) + var dev_out = dctx.enqueue_create_buffer[DTYPE](num_pixels * 4) + dctx.enqueue_copy(dev_in, in_p) + + _launch_rgb_ratio_gpu( + dctx, + Int(dev_in.unsafe_ptr()), + Int(dev_out.unsafe_ptr()), + params.white_target(), + params.black_target(), + params.paper_exposure(), + params.film_fog(), + params.film_power(), + params.paper_power(), + num_pixels, + ) + + dctx.enqueue_copy(out_p, dev_out) + dctx.synchronize() + except e: + print("GPU Run Error (RGB Ratio):", String(e)) + else: + var rt = RuntimeLayout[IMAGE_LAYOUT].row_major( + IndexList[3](h, w, CHANNELS) + ) + var in_t = LayoutTensor[DTYPE, IMAGE_LAYOUT, MutAnyOrigin](in_p, rt) + var out_t = LayoutTensor[DTYPE, IMAGE_LAYOUT, MutAnyOrigin](out_p, rt) + var wt = params.white_target() + var bt = params.black_target() + var pe = params.paper_exposure() + var ff = params.film_fog() + var fp = params.film_power() + var pp = params.paper_power() + for i in range(num_pixels): + var px = in_t.load[width=4](Index(i // w, i % w, 0)) + var r = apply_sigmoid_rgb_ratio( + px[0], px[1], px[2], px[3], wt, bt, pe, ff, fp, pp + ) + out_t.store[width=4](Index(i // w, i % w, 0), r) + + +@export +fn sigmoid_mojo_per_channel( + ctx_addr: Int, + in_addr: Int, + out_addr: Int, + width: Int32, + height: Int32, + p_addr: Int, +): + var ctx_p = UnsafePointer[MojoCtx, MutAnyOrigin]( + unsafe_from_address=ctx_addr + ) + var use_gpu = ctx_p[0].use_gpu != 0 + var dctx_addr = ctx_p[0].dctx_addr + var params = CParamsView(p_addr) + var in_p = UnsafePointer[Float32, MutAnyOrigin](unsafe_from_address=in_addr) + var out_p = UnsafePointer[Float32, MutAnyOrigin]( + unsafe_from_address=out_addr + ) + var h = Int(height) + var w = Int(width) + var num_pixels = h * w + + if use_gpu and dctx_addr != 0: + try: + var dctx = UnsafePointer[DeviceContext, MutAnyOrigin]( + unsafe_from_address=dctx_addr + )[0] + var dev_in = dctx.enqueue_create_buffer[DTYPE](num_pixels * 4) + var dev_out = dctx.enqueue_create_buffer[DTYPE](num_pixels * 4) + dctx.enqueue_copy(dev_in, in_p) + + _launch_per_channel_gpu( + dctx, + Int(dev_in.unsafe_ptr()), + Int(dev_out.unsafe_ptr()), + params.white_target(), + params.paper_exposure(), + params.film_fog(), + params.film_power(), + params.paper_power(), + params.hue_preservation(), + params.pipe_to_base(), + params.base_to_rendering(), + params.rendering_to_pipe(), + num_pixels, + ) + + dctx.enqueue_copy(out_p, dev_out) + dctx.synchronize() + except e: + print("GPU Error (Per Channel):", String(e)) + else: + var rt = RuntimeLayout[IMAGE_LAYOUT].row_major( + IndexList[3](h, w, CHANNELS) + ) + var in_t = LayoutTensor[DTYPE, IMAGE_LAYOUT, MutAnyOrigin](in_p, rt) + var out_t = LayoutTensor[DTYPE, IMAGE_LAYOUT, MutAnyOrigin](out_p, rt) + var wt = params.white_target() + var pe = params.paper_exposure() + var ff = params.film_fog() + var fp = params.film_power() + var pp = params.paper_power() + var hp = params.hue_preservation() + var ptb = params.pipe_to_base() + var btr = params.base_to_rendering() + var rtp = params.rendering_to_pipe() + for i in range(num_pixels): + var px = in_t.load[width=4](Index(i // w, i % w, 0)) + var r = apply_sigmoid_per_channel( + px[0], + px[1], + px[2], + px[3], + wt, + pe, + ff, + fp, + pp, + hp, + ptb, + btr, + rtp, + ) + out_t.store[width=4](Index(i // w, i % w, 0), r) diff --git a/mojo/pixi.lock b/mojo/pixi.lock new file mode 100644 index 0000000000..c8ff562623 --- /dev/null +++ b/mojo/pixi.lock @@ -0,0 +1,843 @@ +version: 6 +environments: + default: + channels: + - url: https://conda.modular.com/max-nightly/ + - url: https://conda.anaconda.org/conda-forge/ + options: + pypi-prerelease-mode: if-necessary-or-explicit + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.3-py314hd8ed1ab_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-5_h47877c9_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.21-h280c20c_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.52.0-hf4e2dac_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.modular.com/max-nightly/linux-64/max-26.3.0.dev2026031105-3.14release.conda + - conda: https://conda.modular.com/max-nightly/linux-64/max-core-26.3.0.dev2026031105-release.conda + - conda: https://conda.modular.com/max-nightly/noarch/mblack-26.3.0.dev2026031105-release.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda + - conda: https://conda.modular.com/max-nightly/linux-64/mojo-0.26.3.0.dev2026031105-release.conda + - conda: https://conda.modular.com/max-nightly/linux-64/mojo-compiler-0.26.3.0.dev2026031105-release.conda + - conda: https://conda.modular.com/max-nightly/noarch/mojo-python-0.26.3.0.dev2026031105-release.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.1.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.2-py314h2b28147_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.3-h32b2ec7_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.3-h4df99d1_101.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py312hda471dd_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-14.3.3-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.3-py314h5bd0f2a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h41580af_10.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda +packages: +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + build_number: 20 + sha256: 1dd3fffd892081df9726d7eb7e0dea6198962ba775bd88842135a4ddb4deb3c9 + md5: a9f577daf3de00bca7c3c76c0ecbd1de + depends: + - __glibc >=2.17,<3.0.a0 + - libgomp >=7.5.0 + constrains: + - openmp_impl <0.0a0 + license: BSD-3-Clause + license_family: BSD + size: 28948 + timestamp: 1770939786096 +- conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda + sha256: a3967b937b9abf0f2a99f3173fa4630293979bd1644709d89580e7c62a544661 + md5: aaa2a381ccc56eac91d63b6c1240312f + depends: + - cpython + - python-gil + license: MIT + license_family: MIT + size: 8191 + timestamp: 1744137672556 +- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda + sha256: 0b75d45f0bba3e95dc693336fa51f40ea28c980131fec438afb7ce6118ed05f6 + md5: d2ffd7602c02f2b316fd921d39876885 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: bzip2-1.0.6 + license_family: BSD + size: 260182 + timestamp: 1771350215188 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + sha256: 67cc7101b36421c5913a1687ef1b99f85b5d6868da3abbf6ec1a4181e79782fc + md5: 4492fd26db29495f0ba23f146cd5638d + depends: + - __unix + license: ISC + size: 147413 + timestamp: 1772006283803 +- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda + sha256: 38cfe1ee75b21a8361c8824f5544c3866f303af1762693a178266d7f198e8715 + md5: ea8a6c3256897cc31263de9f455e25d9 + depends: + - python >=3.10 + - __unix + - python + license: BSD-3-Clause + license_family: BSD + size: 97676 + timestamp: 1764518652276 +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.3-py314hd8ed1ab_101.conda + noarch: generic + sha256: 91b06300879df746214f7363d6c27c2489c80732e46a369eb2afc234bcafb44c + md5: 3bb89e4f795e5414addaa531d6b1500a + depends: + - python >=3.14,<3.15.0a0 + - python_abi * *_cp314 + license: Python-2.0 + size: 50078 + timestamp: 1770674447292 +- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda + sha256: 142a722072fa96cf16ff98eaaf641f54ab84744af81754c292cb81e0881c0329 + md5: 186a18e3ba246eccfc7cff00cd19a870 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + license: MIT + license_family: MIT + size: 12728445 + timestamp: 1767969922681 +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda + sha256: c18ab120a0613ada4391b15981d86ff777b5690ca461ea7e9e49531e8f374745 + md5: 63ccfdc3a3ce25b027b8767eb722fca8 + depends: + - python >=3.9 + - zipp >=3.20 + - python + license: Apache-2.0 + license_family: APACHE + size: 34641 + timestamp: 1747934053147 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.6.3-pyhd8ed1ab_1.conda + sha256: 19d8bd5bb2fde910ec59e081eeb59529491995ce0d653a5209366611023a0b3a + md5: 4ebae00eae9705b0c3d6d1018a81d047 + depends: + - importlib-metadata >=4.8.3 + - jupyter_core >=4.12,!=5.0.* + - python >=3.9 + - python-dateutil >=2.8.2 + - pyzmq >=23.0 + - tornado >=6.2 + - traitlets >=5.3 + license: BSD-3-Clause + license_family: BSD + size: 106342 + timestamp: 1733441040958 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda + sha256: 1d34b80e5bfcd5323f104dbf99a2aafc0e5d823019d626d0dce5d3d356a2a52a + md5: b38fe4e78ee75def7e599843ef4c1ab0 + depends: + - __unix + - python + - platformdirs >=2.5 + - python >=3.10 + - traitlets >=5.3 + - python + constrains: + - pywin32 >=300 + license: BSD-3-Clause + license_family: BSD + size: 65503 + timestamp: 1760643864586 +- conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda + sha256: 0960d06048a7185d3542d850986d807c6e37ca2e644342dd0c72feefcf26c2a4 + md5: b38117a3c920364aff79f870c984b4a3 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: LGPL-2.1-or-later + size: 134088 + timestamp: 1754905959823 +- conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda + sha256: 3e307628ca3527448dd1cb14ad7bb9d04d1d28c7d4c5f97ba196ae984571dd25 + md5: fb53fb07ce46a575c5d004bbc96032c2 + depends: + - __glibc >=2.17,<3.0.a0 + - keyutils >=1.6.3,<2.0a0 + - libedit >=3.1.20250104,<3.2.0a0 + - libedit >=3.1.20250104,<4.0a0 + - libgcc >=14 + - libstdcxx >=14 + - openssl >=3.5.5,<4.0a0 + license: MIT + license_family: MIT + size: 1386730 + timestamp: 1769769569681 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_101.conda + sha256: 565941ac1f8b0d2f2e8f02827cbca648f4d18cd461afc31f15604cd291b5c5f3 + md5: 12bd9a3f089ee6c9266a37dab82afabd + depends: + - __glibc >=2.17,<3.0.a0 + - zstd >=1.5.7,<1.6.0a0 + constrains: + - binutils_impl_linux-64 2.45.1 + license: GPL-3.0-only + license_family: GPL + size: 725507 + timestamp: 1770267139900 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda + build_number: 5 + sha256: 18c72545080b86739352482ba14ba2c4815e19e26a7417ca21a95b76ec8da24c + md5: c160954f7418d7b6e87eaf05a8913fa9 + depends: + - libopenblas >=0.3.30,<0.3.31.0a0 + - libopenblas >=0.3.30,<1.0a0 + constrains: + - mkl <2026 + - liblapack 3.11.0 5*_openblas + - libcblas 3.11.0 5*_openblas + - blas 2.305 openblas + - liblapacke 3.11.0 5*_openblas + license: BSD-3-Clause + license_family: BSD + size: 18213 + timestamp: 1765818813880 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda + build_number: 5 + sha256: 0cbdcc67901e02dc17f1d19e1f9170610bd828100dc207de4d5b6b8ad1ae7ad8 + md5: 6636a2b6f1a87572df2970d3ebc87cc0 + depends: + - libblas 3.11.0 5_h4a7cf45_openblas + constrains: + - liblapacke 3.11.0 5*_openblas + - blas 2.305 openblas + - liblapack 3.11.0 5*_openblas + license: BSD-3-Clause + license_family: BSD + size: 18194 + timestamp: 1765818837135 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda + sha256: d789471216e7aba3c184cd054ed61ce3f6dac6f87a50ec69291b9297f8c18724 + md5: c277e0a4d549b03ac1e9d6cbbe3d017b + depends: + - ncurses + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - ncurses >=6.5,<7.0a0 + license: BSD-2-Clause + license_family: BSD + size: 134676 + timestamp: 1738479519902 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda + sha256: d78f1d3bea8c031d2f032b760f36676d87929b18146351c4464c66b0869df3f5 + md5: e7f7ce06ec24cfcfb9e36d28cf82ba57 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + constrains: + - expat 2.7.4.* + license: MIT + license_family: MIT + size: 76798 + timestamp: 1771259418166 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda + sha256: 31f19b6a88ce40ebc0d5a992c131f57d919f73c0b92cd1617a5bec83f6e961e6 + md5: a360c33a5abe61c07959e449fa1453eb + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: MIT + license_family: MIT + size: 58592 + timestamp: 1769456073053 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda + sha256: faf7d2017b4d718951e3a59d081eb09759152f93038479b768e3d612688f83f5 + md5: 0aa00f03f9e39fb9876085dee11a85d4 + depends: + - __glibc >=2.17,<3.0.a0 + - _openmp_mutex >=4.5 + constrains: + - libgcc-ng ==15.2.0=*_18 + - libgomp 15.2.0 he0feb66_18 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 1041788 + timestamp: 1771378212382 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_18.conda + sha256: d2c9fad338fd85e4487424865da8e74006ab2e2475bd788f624d7a39b2a72aee + md5: 9063115da5bc35fdc3e1002e69b9ef6e + depends: + - libgfortran5 15.2.0 h68bc16d_18 + constrains: + - libgfortran-ng ==15.2.0=*_18 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 27523 + timestamp: 1771378269450 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_18.conda + sha256: 539b57cf50ec85509a94ba9949b7e30717839e4d694bc94f30d41c9d34de2d12 + md5: 646855f357199a12f02a87382d429b75 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15.2.0 + constrains: + - libgfortran 15.2.0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 2482475 + timestamp: 1771378241063 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda + sha256: 21337ab58e5e0649d869ab168d4e609b033509de22521de1bfed0c031bfc5110 + md5: 239c5e9546c38a1e884d69effcf4c882 + depends: + - __glibc >=2.17,<3.0.a0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 603262 + timestamp: 1771378117851 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-5_h47877c9_openblas.conda + build_number: 5 + sha256: c723b6599fcd4c6c75dee728359ef418307280fa3e2ee376e14e85e5bbdda053 + md5: b38076eb5c8e40d0106beda6f95d7609 + depends: + - libblas 3.11.0 5_h4a7cf45_openblas + constrains: + - blas 2.305 openblas + - liblapacke 3.11.0 5*_openblas + - libcblas 3.11.0 5*_openblas + license: BSD-3-Clause + license_family: BSD + size: 18200 + timestamp: 1765818857876 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda + sha256: 755c55ebab181d678c12e49cced893598f2bab22d582fbbf4d8b83c18be207eb + md5: c7c83eecbb72d88b940c249af56c8b17 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + constrains: + - xz 5.8.2.* + license: 0BSD + size: 113207 + timestamp: 1768752626120 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda + sha256: fe171ed5cf5959993d43ff72de7596e8ac2853e9021dec0344e583734f1e0843 + md5: 2c21e66f50753a083cbe6b80f38268fa + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: BSD-2-Clause + license_family: BSD + size: 92400 + timestamp: 1769482286018 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda + sha256: 199d79c237afb0d4780ccd2fbf829cea80743df60df4705202558675e07dd2c5 + md5: be43915efc66345cccb3c310b6ed0374 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libgfortran + - libgfortran5 >=14.3.0 + constrains: + - openblas >=0.3.30,<0.3.31.0a0 + license: BSD-3-Clause + license_family: BSD + size: 5927939 + timestamp: 1763114673331 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.21-h280c20c_3.conda + sha256: 64e5c80cbce4680a2d25179949739a6def695d72c40ca28f010711764e372d97 + md5: 7af961ef4aa2c1136e11dd43ded245ab + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + license: ISC + size: 277661 + timestamp: 1772479381288 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.52.0-hf4e2dac_0.conda + sha256: d716847b7deca293d2e49ed1c8ab9e4b9e04b9d780aea49a97c26925b28a7993 + md5: fd893f6a3002a635b5e50ceb9dd2c0f4 + depends: + - __glibc >=2.17,<3.0.a0 + - icu >=78.2,<79.0a0 + - libgcc >=14 + - libzlib >=1.3.1,<2.0a0 + license: blessing + size: 951405 + timestamp: 1772818874251 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda + sha256: 78668020064fdaa27e9ab65cd2997e2c837b564ab26ce3bf0e58a2ce1a525c6e + md5: 1b08cd684f34175e4514474793d44bcb + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc 15.2.0 he0feb66_18 + constrains: + - libstdcxx-ng ==15.2.0=*_18 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 5852330 + timestamp: 1771378262446 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda + sha256: 1a7539cfa7df00714e8943e18de0b06cceef6778e420a5ee3a2a145773758aee + md5: db409b7c1720428638e7c0d509d3e1b5 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: BSD-3-Clause + license_family: BSD + size: 40311 + timestamp: 1766271528534 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda + sha256: d4bfe88d7cb447768e31650f06257995601f89076080e76df55e3112d4e47dc4 + md5: edb0dca6bc32e4f4789199455a1dbeb8 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + constrains: + - zlib 1.3.1 *_2 + license: Zlib + license_family: Other + size: 60963 + timestamp: 1727963148474 +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda + sha256: 7b1da4b5c40385791dbc3cc85ceea9fad5da680a27d5d3cb8bfaa185e304a89e + md5: 5b5203189eb668f042ac2b0826244964 + depends: + - mdurl >=0.1,<1 + - python >=3.10 + license: MIT + license_family: MIT + size: 64736 + timestamp: 1754951288511 +- conda: https://conda.modular.com/max-nightly/linux-64/max-26.3.0.dev2026031105-3.14release.conda + sha256: e6407c6222b5a0ccc4fd7270e55326f39f1026531bde13d3b12586861a2f4710 + md5: c3c4ea5254ba1a4962b1d7c7ba9e7461 + depends: + - numpy >=1.18 + - typing-extensions >=4.12.2 + - pyyaml >=6.0.1 + - rich >=13.0.1 + - python 3.14.* + - python-gil + - max-core ==26.3.0.dev2026031105 + license: LicenseRef-Modular-Proprietary + size: 4231736 + timestamp: 1773207424284 +- conda: https://conda.modular.com/max-nightly/linux-64/max-core-26.3.0.dev2026031105-release.conda + sha256: 5fb9f5db6c0a463d2b25185f7bcf9fce9efbd67dbcd31a88ad13b65f2371d540 + md5: 689a17beb15fc6b8b14d188a750c2d85 + depends: + - mojo-compiler ==0.26.3.0.dev2026031105 + license: LicenseRef-Modular-Proprietary + size: 137553590 + timestamp: 1773207447229 +- conda: https://conda.modular.com/max-nightly/noarch/mblack-26.3.0.dev2026031105-release.conda + noarch: python + sha256: dd93df3438e366c447af4e2ae2fa3811b83a2a68fa69ce8f9fbbc33daf06ad80 + md5: 33c8f9a54a3122c0a02073f8f4138bb1 + depends: + - python >=3.10 + - click >=8.0.0 + - mypy_extensions >=0.4.3 + - packaging >=22.0 + - pathspec >=0.9.0 + - platformdirs >=2 + - tomli >=1.1.0 + license: LicenseRef-Modular-Proprietary + size: 133842 + timestamp: 1773207196055 +- conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda + sha256: 78c1bbe1723449c52b7a9df1af2ee5f005209f67e40b6e1d3c7619127c43b1c7 + md5: 592132998493b3ff25fd7479396e8351 + depends: + - python >=3.9 + license: MIT + license_family: MIT + size: 14465 + timestamp: 1733255681319 +- conda: https://conda.modular.com/max-nightly/linux-64/mojo-0.26.3.0.dev2026031105-release.conda + sha256: ecf51beda01f003878e078c9898c9fccf90354aa321a6964e2e1bf51fcc0eeea + md5: 923cb2a3993db48806d77c5cbc46587c + depends: + - python >=3.10 + - mojo-compiler ==0.26.3.0.dev2026031105 + - mblack ==26.3.0.dev2026031105 + - jupyter_client >=8.6.2,<8.7 + license: LicenseRef-Modular-Proprietary + size: 89318428 + timestamp: 1773207351958 +- conda: https://conda.modular.com/max-nightly/linux-64/mojo-compiler-0.26.3.0.dev2026031105-release.conda + sha256: 03eeb0e485c57def8067c0534658b185c984afbc27e77b57b55262dbc3fad8b8 + md5: 86ab7d0febcb6717e3c19018884cdbe4 + depends: + - mojo-python ==0.26.3.0.dev2026031105 + license: LicenseRef-Modular-Proprietary + size: 88636856 + timestamp: 1773207323233 +- conda: https://conda.modular.com/max-nightly/noarch/mojo-python-0.26.3.0.dev2026031105-release.conda + noarch: python + sha256: c6af0e06dc5fa3e1b0dbe3f9753c3da7653090e020720dcfba063f04911fc157 + md5: 647d60ca954e6f019a974171c1dfc830 + depends: + - python >=3.10 + license: LicenseRef-Modular-Proprietary + size: 22930 + timestamp: 1773207195039 +- conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.1.0-pyha770c72_0.conda + sha256: 6ed158e4e5dd8f6a10ad9e525631e35cee8557718f83de7a4e3966b1f772c4b1 + md5: e9c622e0d00fa24a6292279af3ab6d06 + depends: + - python >=3.9 + license: MIT + license_family: MIT + size: 11766 + timestamp: 1745776666688 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda + sha256: 3fde293232fa3fca98635e1167de6b7c7fda83caf24b9d6c91ec9eefb4f4d586 + md5: 47e340acb35de30501a76c7c799c41d7 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: X11 AND BSD-3-Clause + size: 891641 + timestamp: 1738195959188 +- conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.2-py314h2b28147_1.conda + sha256: 1d8377c8001c15ed12c2713b723213474b435706ab9d34ede69795d64af9e94d + md5: 4ea6b620fdf24a1a0bc4f1c7134dfafb + depends: + - python + - libstdcxx >=14 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - libcblas >=3.9.0,<4.0a0 + - python_abi 3.14.* *_cp314 + - libblas >=3.9.0,<4.0a0 + - liblapack >=3.9.0,<4.0a0 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + size: 8926994 + timestamp: 1770098474394 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda + sha256: 44c877f8af015332a5d12f5ff0fb20ca32f896526a7d0cdb30c769df1144fb5c + md5: f61eb8cd60ff9057122a3d338b99c00f + depends: + - __glibc >=2.17,<3.0.a0 + - ca-certificates + - libgcc >=14 + license: Apache-2.0 + license_family: Apache + size: 3164551 + timestamp: 1769555830639 +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda + sha256: c1fc0f953048f743385d31c468b4a678b3ad20caffdeaa94bed85ba63049fd58 + md5: b76541e68fea4d511b1ac46a28dcd2c6 + depends: + - python >=3.8 + - python + license: Apache-2.0 + license_family: APACHE + size: 72010 + timestamp: 1769093650580 +- conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda + sha256: 29ea20d0faf20374fcd61c25f6d32fb8e9a2c786a7f1473a0c3ead359470fbe1 + md5: 2908273ac396d2cd210a8127f5f1c0d6 + depends: + - python >=3.10 + license: MPL-2.0 + license_family: MOZILLA + size: 53739 + timestamp: 1769677743677 +- conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda + sha256: 0289f0a38337ee201d984f8f31f11f6ef076cfbbfd0ab9181d12d9d1d099bf46 + md5: 82c1787f2a65c0155ef9652466ee98d6 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + size: 25646 + timestamp: 1773199142345 +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda + sha256: 5577623b9f6685ece2697c6eb7511b4c9ac5fb607c9babc2646c811b428fd46a + md5: 6b6ece66ebcae2d5f326c77ef2c5a066 + depends: + - python >=3.9 + license: BSD-2-Clause + license_family: BSD + size: 889287 + timestamp: 1750615908735 +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.3-h32b2ec7_101_cp314.conda + build_number: 101 + sha256: cb0628c5f1732f889f53a877484da98f5a0e0f47326622671396fb4f2b0cd6bd + md5: c014ad06e60441661737121d3eae8a60 + depends: + - __glibc >=2.17,<3.0.a0 + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-64 >=2.36.1 + - libexpat >=2.7.3,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - libgcc >=14 + - liblzma >=5.8.2,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libuuid >=2.41.3,<3.0a0 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.5,<4.0a0 + - python_abi 3.14.* *_cp314 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 + size: 36702440 + timestamp: 1770675584356 + python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda + sha256: d6a17ece93bbd5139e02d2bd7dbfa80bee1a4261dced63f65f679121686bf664 + md5: 5b8d21249ff20967101ffa321cab24e8 + depends: + - python >=3.9 + - six >=1.5 + - python + license: Apache-2.0 + license_family: APACHE + size: 233310 + timestamp: 1751104122689 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.3-h4df99d1_101.conda + sha256: 233aebd94c704ac112afefbb29cf4170b7bc606e22958906f2672081bc50638a + md5: 235765e4ea0d0301c75965985163b5a1 + depends: + - cpython 3.14.3.* + - python_abi * *_cp314 + license: Python-2.0 + size: 50062 + timestamp: 1770674497152 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + build_number: 8 + sha256: ad6d2e9ac39751cc0529dd1566a26751a0bf2542adb0c232533d32e176e21db5 + md5: 0539938c55b6b1a59b560e843ad864a4 + constrains: + - python 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + size: 6989 + timestamp: 1752805904792 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda + sha256: b318fb070c7a1f89980ef124b80a0b5ccf3928143708a85e0053cde0169c699d + md5: 2035f68f96be30dc60a5dfd7452c7941 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + size: 202391 + timestamp: 1770223462836 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py312hda471dd_2.conda + noarch: python + sha256: be66c1f85c3b48137200d62c12d918f4f8ad329423daef04fed292818efd3c28 + md5: 082985717303dab433c976986c674b35 + depends: + - python + - libgcc >=14 + - libstdcxx >=14 + - __glibc >=2.17,<3.0.a0 + - zeromq >=4.3.5,<4.4.0a0 + - _python_abi3_support 1.* + - cpython >=3.12 + license: BSD-3-Clause + license_family: BSD + size: 211567 + timestamp: 1771716961404 +- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + sha256: 12ffde5a6f958e285aa22c191ca01bbd3d6e710aa852e00618fa6ddc59149002 + md5: d7d95fc8287ea7bf33e0e7116d2b95ec + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - ncurses >=6.5,<7.0a0 + license: GPL-3.0-only + license_family: GPL + size: 345073 + timestamp: 1765813471974 +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-14.3.3-pyhcf101f3_0.conda + sha256: b06ce84d6a10c266811a7d3adbfa1c11f13393b91cc6f8a5b468277d90be9590 + md5: 7a6289c50631d620652f5045a63eb573 + depends: + - markdown-it-py >=2.2.0 + - pygments >=2.13.0,<3.0.0 + - python >=3.10 + - typing_extensions >=4.0.0,<5.0.0 + - python + license: MIT + license_family: MIT + size: 208472 + timestamp: 1771572730357 +- conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + sha256: 458227f759d5e3fcec5d9b7acce54e10c9e1f4f4b7ec978f3bfd54ce4ee9853d + md5: 3339e3b65d58accf4ca4fb8748ab16b3 + depends: + - python >=3.9 + - python + license: MIT + license_family: MIT + size: 18455 + timestamp: 1753199211006 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + sha256: cafeec44494f842ffeca27e9c8b0c27ed714f93ac77ddadc6aaf726b5554ebac + md5: cffd3bdd58090148f4cfcd831f4b26ab + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libzlib >=1.3.1,<2.0a0 + constrains: + - xorg-libx11 >=1.8.12,<2.0a0 + license: TCL + license_family: BSD + size: 3301196 + timestamp: 1769460227866 +- conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda + sha256: 62940c563de45790ba0f076b9f2085a842a65662268b02dd136a8e9b1eaf47a8 + md5: 72e780e9aa2d0a3295f59b1874e3768b + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + size: 21453 + timestamp: 1768146676791 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.3-py314h5bd0f2a_0.conda + sha256: b8f9f9ae508d79c9c697eb01b6a8d2ed4bc1899370f44aa6497c8abbd15988ea + md5: e35f08043f54d26a1be93fdbf90d30c3 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: Apache-2.0 + license_family: Apache + size: 905436 + timestamp: 1765458949518 +- conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda + sha256: f39a5620c6e8e9e98357507262a7869de2ae8cc07da8b7f84e517c9fd6c2b959 + md5: 019a7385be9af33791c989871317e1ed + depends: + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + size: 110051 + timestamp: 1733367480074 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + sha256: 7c2df5721c742c2a47b2c8f960e718c930031663ac1174da67c1ed5999f7938c + md5: edd329d7d3a4ab45dcf905899a7a6115 + depends: + - typing_extensions ==4.15.0 pyhcf101f3_0 + license: PSF-2.0 + license_family: PSF + size: 91383 + timestamp: 1756220668932 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + sha256: 032271135bca55aeb156cee361c81350c6f3fb203f57d024d7e5a1fc9ef18731 + md5: 0caa1af407ecff61170c9437a808404d + depends: + - python >=3.10 + - python + license: PSF-2.0 + license_family: PSF + size: 51692 + timestamp: 1756220668932 +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + sha256: 1d30098909076af33a35017eed6f2953af1c769e273a0626a04722ac4acaba3c + md5: ad659d0a2b3e47e38d829aa8cad2d610 + license: LicenseRef-Public-Domain + size: 119135 + timestamp: 1767016325805 +- conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda + sha256: 6d9ea2f731e284e9316d95fa61869fe7bbba33df7929f82693c121022810f4ad + md5: a77f85f77be52ff59391544bfe73390a + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + license: MIT + license_family: MIT + size: 85189 + timestamp: 1753484064210 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h41580af_10.conda + sha256: 325d370b28e2b9cc1f765c5b4cdb394c91a5d958fbd15da1a14607a28fee09f6 + md5: 755b096086851e1193f3b10347415d7c + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=14 + - krb5 >=1.22.2,<1.23.0a0 + - libsodium >=1.0.21,<1.0.22.0a0 + license: MPL-2.0 + license_family: MOZILLA + size: 311150 + timestamp: 1772476812121 +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + sha256: b4533f7d9efc976511a73ef7d4a2473406d7f4c750884be8e8620b0ce70f4dae + md5: 30cd29cb87d819caead4d55184c1d115 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + size: 24194 + timestamp: 1764460141901 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + sha256: 68f0206ca6e98fea941e5717cec780ed2873ffabc0e1ed34428c061e2c6268c7 + md5: 4a13eeac0b5c8e5b8ab496e6c4ddd829 + depends: + - __glibc >=2.17,<3.0.a0 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + size: 601375 + timestamp: 1764777111296 diff --git a/mojo/pixi.toml b/mojo/pixi.toml new file mode 100644 index 0000000000..37ff9cc53a --- /dev/null +++ b/mojo/pixi.toml @@ -0,0 +1,14 @@ +[workspace] +name = "darktable-mojo" +authors = ["maxchisto "] +channels = ["https://conda.modular.com/max-nightly", "conda-forge"] +platforms = ["linux-64"] +version = "0.1.0" + +[tasks] +build-lib = "mojo build -I . iop/sigmoid/lib.mojo --emit shared-lib -o libsigmoid_mojo.so" +bench = "mojo bench/sigmoid_bench.mojo" + +[dependencies] +mojo = ">=0.26.3.0.dev2026031105,<0.27" +max = ">=26.3.0.dev2026031105,<27" diff --git a/mojo/sigmoid_build_instructions.md b/mojo/sigmoid_build_instructions.md new file mode 100644 index 0000000000..dc107c6639 --- /dev/null +++ b/mojo/sigmoid_build_instructions.md @@ -0,0 +1,39 @@ +# Build Instructions + +## 1. Compile the Mojo Module (`libsigmoid_mojo.so`) + +The Mojo code provides the core processing logic and kernels. + +```bash +cd ~/code/darktable/mojo +make build +``` + +The resulting `libsigmoid_mojo.so` contains the following exported symbols used by the C bridge: +- `sigmoid_mojo_init` +- `sigmoid_mojo_destroy` +- `sigmoid_mojo_rgb_ratio` +- `sigmoid_mojo_per_channel` + +## 2. Compile the C-Bridge Plugin (`libsigmoid.so`) + +The C part (`src/iop/sigmoid.c`) handles the darktable user interface and parameter management. It loads the Mojo shared library at runtime. + +```bash +./build_sigmoid_iop.sh +``` + + +## 3. Installation + +Both shared libraries must be placed in the darktable plugins directory so that darktable can find the plugin and the plugin can find the Mojo library. + +```bash +# Copy the Mojo library +sudo cp libsigmoid_mojo.so /usr/lib/darktable/plugins/ + +# Copy the C bridge plugin +sudo cp libsigmoid.so /usr/lib/darktable/plugins/ +``` + +> The C code in `src/iop/sigmoid.c` uses `dlopen("libsigmoid_mojo.so", RTLD_LAZY | RTLD_LOCAL)` in `init_global` to load the Mojo module. diff --git a/src/external/OpenCL b/src/external/OpenCL deleted file mode 160000 index 8a97ebc88d..0000000000 --- a/src/external/OpenCL +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8a97ebc88daa3495d6f57ec10bb515224400186f diff --git a/src/external/OpenCL/.gitignore b/src/external/OpenCL/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/external/lua-scripts b/src/external/lua-scripts deleted file mode 160000 index db505f1e0a..0000000000 --- a/src/external/lua-scripts +++ /dev/null @@ -1 +0,0 @@ -Subproject commit db505f1e0a089b210f5afa653e53ebd32e5a82b0 diff --git a/src/external/lua-scripts/.gitignore b/src/external/lua-scripts/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/iop/sigmoid.c b/src/iop/sigmoid.c index cbd96d7725..b9301431b7 100644 --- a/src/iop/sigmoid.c +++ b/src/iop/sigmoid.c @@ -27,9 +27,11 @@ #include "gui/gtk.h" #include "gui/presets.h" #include "iop/iop_api.h" +#include "common/opencl.h" #include #include +#include DT_MODULE_INTROSPECTION(3, dt_iop_sigmoid_params_t) @@ -180,10 +182,38 @@ typedef struct dt_iop_sigmoid_gui_data_t dt_gui_collapsible_section_t display_luminance_section, primaries_section; } dt_iop_sigmoid_gui_data_t; +typedef struct { + float white_target[4]; + float black_target[4]; + float paper_exposure[4]; + float film_fog[4]; + float film_power[4]; + float paper_power[4]; + float contrast_power[4]; + float skew_power[4]; + float hue_preservation[4]; + float pipe_to_base[16]; + float base_to_rendering[16]; + float rendering_to_pipe[16]; +} SigmoidMojoParams; + +typedef void (*mojo_init_fn)(uintptr_t *ctx, int use_gpu); +typedef void (*mojo_destroy_fn)(uintptr_t ctx); +typedef void (*mojo_rgb_ratio_fn)(uintptr_t ctx, float *in, float *out, int32_t width, int32_t height, void *params); +typedef void (*mojo_per_channel_fn)(uintptr_t ctx, float *in, float *out, int32_t width, int32_t height, void *params); + typedef struct dt_iop_sigmoid_global_data_t { int kernel_sigmoid_loglogistic_per_channel; int kernel_sigmoid_loglogistic_rgb_ratio; + + void *mojo_lib; + uintptr_t mojo_ctx_cpu; + uintptr_t mojo_ctx_gpu; + mojo_init_fn mojo_init; + mojo_destroy_fn mojo_destroy; + mojo_rgb_ratio_fn mojo_rgb_ratio; + mojo_per_channel_fn mojo_per_channel; } dt_iop_sigmoid_global_data_t; @@ -760,6 +790,40 @@ void process_loglogistic_per_channel(dt_develop_t *dev, } } +static SigmoidMojoParams _build_mojo_params(dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece) +{ + const dt_iop_sigmoid_data_t *d = piece->data; + SigmoidMojoParams p = {0}; + + for(int i = 0; i < 4; i++) { + p.white_target[i] = d->white_target; + p.black_target[i] = d->black_target; + p.paper_exposure[i] = d->paper_exposure; + p.film_fog[i] = d->film_fog; + p.film_power[i] = d->film_power; + p.paper_power[i] = d->paper_power; + p.contrast_power[i] = d->film_power; + p.skew_power[i] = d->paper_power; + p.hue_preservation[i] = d->hue_preservation; + } + + const dt_iop_order_iccprofile_info_t *pipe_work_profile = dt_ioppr_get_pipe_work_profile_info(piece->pipe); + const dt_iop_order_iccprofile_info_t *base_profile = _get_base_profile(self->dev, pipe_work_profile, d->base_primaries); + dt_colormatrix_t pipe_to_base_transposed, base_to_rendering_transposed, rendering_to_pipe_transposed; + dt_colormatrix_t pipe_to_base, base_to_rendering, rendering_to_pipe; + + _calculate_adjusted_primaries(d, pipe_work_profile, base_profile, pipe_to_base_transposed, base_to_rendering_transposed, rendering_to_pipe_transposed); + transpose_3xSSE(pipe_to_base_transposed, pipe_to_base); + transpose_3xSSE(base_to_rendering_transposed, base_to_rendering); + transpose_3xSSE(rendering_to_pipe_transposed, rendering_to_pipe); + + memcpy(p.pipe_to_base, pipe_to_base, sizeof(pipe_to_base)); + memcpy(p.base_to_rendering, base_to_rendering, sizeof(base_to_rendering)); + memcpy(p.rendering_to_pipe, rendering_to_pipe, sizeof(rendering_to_pipe)); + + return p; +} + /** process, all real work is done here. */ void process(dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, @@ -768,8 +832,22 @@ void process(dt_iop_module_t *self, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out) { - // this is called for preview and full pipe separately, each with its own pixelpipe piece. const dt_iop_sigmoid_data_t *module_data = piece->data; + const dt_iop_sigmoid_global_data_t *gd = self->global_data; + + if(gd && gd->mojo_lib && gd->mojo_per_channel && gd->mojo_rgb_ratio) + { + SigmoidMojoParams p = _build_mojo_params(self, piece); + const int w = roi_in->width, h = roi_in->height; + int use_gpu = dt_opencl_is_enabled() ? 1 : 0; + uintptr_t ctx = use_gpu ? gd->mojo_ctx_gpu : gd->mojo_ctx_cpu; + + if(module_data->color_processing == DT_SIGMOID_METHOD_PER_CHANNEL) + gd->mojo_per_channel(ctx, (float *)ivoid, (float *)ovoid, w, h, &p); + else + gd->mojo_rgb_ratio(ctx, (float *)ivoid, (float *)ovoid, w, h, &p); + return; + } if(module_data->color_processing == DT_SIGMOID_METHOD_PER_CHANNEL) { @@ -781,87 +859,42 @@ void process(dt_iop_module_t *self, } } -#ifdef HAVE_OPENCL -int process_cl(dt_iop_module_t *self, - dt_dev_pixelpipe_iop_t *piece, - cl_mem dev_in, - cl_mem dev_out, - const dt_iop_roi_t *const roi_in, - const dt_iop_roi_t *const roi_out) -{ - const dt_iop_sigmoid_data_t *const d = piece->data; - const dt_iop_sigmoid_global_data_t *const gd = self->global_data; - cl_int err = CL_MEM_OBJECT_ALLOCATION_FAILURE; - const int devid = piece->pipe->devid; - const int width = roi_in->width; - const int height = roi_in->height; - const float white_target = d->white_target; - const float paper_exp = d->paper_exposure; - const float film_fog = d->film_fog; - const float contrast_power = d->film_power; - const float skew_power = d->paper_power; +void init_global(dt_iop_module_so_t *self) +{ + dt_iop_sigmoid_global_data_t *gd = calloc(1, sizeof(dt_iop_sigmoid_global_data_t)); + self->data = gd; - const dt_iop_order_iccprofile_info_t *pipe_work_profile = dt_ioppr_get_pipe_work_profile_info(piece->pipe); - const dt_iop_order_iccprofile_info_t *base_profile = _get_base_profile(self->dev, pipe_work_profile, d->base_primaries); - dt_colormatrix_t pipe_to_base_transposed, base_to_rendering_transposed, - rendering_to_pipe_transposed, pipe_to_base, base_to_rendering, rendering_to_pipe; - _calculate_adjusted_primaries(d, pipe_work_profile, base_profile, pipe_to_base_transposed, base_to_rendering_transposed, rendering_to_pipe_transposed); - transpose_3xSSE(pipe_to_base_transposed, pipe_to_base); - transpose_3xSSE(base_to_rendering_transposed, base_to_rendering); - transpose_3xSSE(rendering_to_pipe_transposed, rendering_to_pipe); - const cl_mem dev_pipe_to_base - = dt_opencl_copy_host_to_device_constant(devid, sizeof(pipe_to_base), pipe_to_base); - const cl_mem dev_base_to_rendering - = dt_opencl_copy_host_to_device_constant(devid, sizeof(base_to_rendering), base_to_rendering); - const cl_mem dev_rendering_to_pipe - = dt_opencl_copy_host_to_device_constant(devid, sizeof(rendering_to_pipe), rendering_to_pipe); - if(dev_pipe_to_base == NULL || dev_base_to_rendering == NULL || dev_rendering_to_pipe == NULL) - goto cleanup; - - if(d->color_processing == DT_SIGMOID_METHOD_PER_CHANNEL) + gd->mojo_lib = dlopen("libsigmoid_mojo.so", RTLD_LAZY | RTLD_LOCAL); + if(gd->mojo_lib) { - const float hue_preservation = d->hue_preservation; - err = dt_opencl_enqueue_kernel_2d_args( - devid, gd->kernel_sigmoid_loglogistic_per_channel, width, height, CLARG(dev_in), CLARG(dev_out), - CLARG(width), CLARG(height), CLARG(white_target), CLARG(paper_exp), CLARG(film_fog), CLARG(contrast_power), - CLARG(skew_power), CLARG(hue_preservation), CLARG(dev_pipe_to_base), CLARG(dev_base_to_rendering), CLARG(dev_rendering_to_pipe)); - } - else - { - const float black_target = d->black_target; + gd->mojo_init = (mojo_init_fn)dlsym(gd->mojo_lib, "sigmoid_mojo_init"); + gd->mojo_destroy = (mojo_destroy_fn)dlsym(gd->mojo_lib, "sigmoid_mojo_destroy"); + gd->mojo_rgb_ratio = (mojo_rgb_ratio_fn)dlsym(gd->mojo_lib, "sigmoid_mojo_rgb_ratio"); + gd->mojo_per_channel = (mojo_per_channel_fn)dlsym(gd->mojo_lib, "sigmoid_mojo_per_channel"); - err = dt_opencl_enqueue_kernel_2d_args(devid, gd->kernel_sigmoid_loglogistic_rgb_ratio, width, height, - CLARG(dev_in), CLARG(dev_out), CLARG(width), CLARG(height), - CLARG(white_target), CLARG(black_target), CLARG(paper_exp), - CLARG(film_fog), CLARG(contrast_power), CLARG(skew_power)); + if (gd->mojo_init && gd->mojo_destroy) + { + gd->mojo_init(&gd->mojo_ctx_cpu, 0); // CPU context + gd->mojo_init(&gd->mojo_ctx_gpu, 1); // GPU context + } } - -cleanup: - dt_opencl_release_mem_object(dev_pipe_to_base); - dt_opencl_release_mem_object(dev_base_to_rendering); - dt_opencl_release_mem_object(dev_rendering_to_pipe); - return err; -} -#endif // HAVE_OPENCL - -void init_global(dt_iop_module_so_t *self) -{ - const int program = 36; // sigmoid.cl, from programs.conf - dt_iop_sigmoid_global_data_t *gd = malloc(sizeof(dt_iop_sigmoid_global_data_t)); - - self->data = gd; - gd->kernel_sigmoid_loglogistic_per_channel = dt_opencl_create_kernel(program, "sigmoid_loglogistic_per_channel"); - gd->kernel_sigmoid_loglogistic_rgb_ratio = dt_opencl_create_kernel(program, "sigmoid_loglogistic_rgb_ratio"); } void cleanup_global(dt_iop_module_so_t *self) { - const dt_iop_sigmoid_global_data_t *gd = self->data; - dt_opencl_free_kernel(gd->kernel_sigmoid_loglogistic_per_channel); - dt_opencl_free_kernel(gd->kernel_sigmoid_loglogistic_rgb_ratio); - free(self->data); + dt_iop_sigmoid_global_data_t *gd = self->data; + if(gd) + { + if(gd->mojo_destroy) + { + if(gd->mojo_ctx_cpu) gd->mojo_destroy(gd->mojo_ctx_cpu); + if(gd->mojo_ctx_gpu) gd->mojo_destroy(gd->mojo_ctx_gpu); + } + if(gd->mojo_lib) dlclose(gd->mojo_lib); + free(gd); + } self->data = NULL; }