mirror of
https://github.com/storytold/effectcraft.git
synced 2026-11-07 12:13:22 +00:00
* Viewer exposure on the full float range of 32 bpc frames (#2797) 32 bpc viewer frames on the desktop are rendered without the HDR step (skip_hdr_step, #2916) and kept as half floats in the RAM preview. A display pass on egui-wgpu's device turns each frame into one RGBA8 texture with mips per viewer, in this order: decode, exposure in linear light, Compand / Tone Map, encode, display colour, Show Channel, rounding. Before, exposure was an 8-bit lookup applied after tone mapping, clamping and the display conversion, so -2 EV could not bring values above 1.0 back. - engine: viewer::DisplayPass describes the pass as data; its pixel() is the CPU fallback (no device) and the shader's reference. It replaces exposure_lut / display_transform. FrameEncoding records a frame's curve and the HDR step it still needs. 32 bpc snapshots are taken without the HDR step; snapshot_rgba8 applies it. - ui-egui: FrameImage::CpuF16 (half crate, F16C at run time), byte accounting at 8 bytes a pixel in the cache and the prefetch estimates; display_gpu.rs + display_gpu.wgsl; main viewer, snapshot and passive viewers draw through the pass; the 8-bit image other panels read is made on demand with the HDR step; the Info panel shows float values. - Half-float frames are not written to the disk cache yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Viewer display pass: f16 disk cache entries, window-device gating, review fixes - Disk cache: half-float frame entries (format byte in the entry header, byte planes + LZ4); 8-bit entries keep format 0 and stay valid. 32 bpc viewer frames are written and read again, and the timeline's disk bar sees them. A damaged half-float entry is deleted. - The display pass runs on the window's egui-wgpu device, with or without the GPU compositor (still building, failed, GL fallback). Its pipelines are made inside error scopes; a backend that rejects them gets the CPU pass instead of a blank viewer. - A new LUT of the same size (another ICC profile, Preserve RGB, another display) runs the pass again. - f32 to f16: one pass per L1-sized block, the NaN / infinity fix-up on the bits, no fill of the buffer (4K: 4.7 ms, as the 8-bit conversion). - Mips of odd-sized levels include the last column / row; the snapshot's half floats and texture go with the snapshot; no placeholder texture ids; u64 size checks. - Tests: LUT profiles and negative values against the shader, Bake reruns, the passive viewer's colour, f16 disk round trips; exact comparisons allow 1 LSB on software rasterizers. Docs: the display pass and the f16 disk entries in architecture.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Viewer f16 disk-cache test: temp dir removed on failure too, wait for the queued disk write Review points: the test's directory was only removed by its last statement (now tempfile::TempDir), and the frame is released before its disk write is queued, so flush() could return early (now waits for the entry). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Viewer: oversized half-float frames use the CPU display pass, so exposure/HDR come before the averaging down Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Viewer: fmt and a debug assert for the half-float upload path Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Disk cache: persist_missing also writes half-float frames Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Passive viewer: oversized half-float frames take the CPU display pass instead of leaving a stale texture Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
262 lines
12 KiB
TOML
262 lines
12 KiB
TOML
[workspace]
|
|
resolver = "3"
|
|
members = ["crates/*", "apps/*", "xtask"]
|
|
default-members = ["crates/*", "apps/*"]
|
|
|
|
[workspace.package]
|
|
version = "0.21.0"
|
|
edition = "2024"
|
|
license = "MIT OR Apache-2.0"
|
|
rust-version = "1.95"
|
|
repository = "https://github.com/storytold/effectcraft"
|
|
|
|
[workspace.dependencies]
|
|
craft-pdf = { git = "https://github.com/storytold/craft-libs", rev = "92d392cff132eaf53e13afff77f38b5c11b73aa0", version = "=0.1.0", default-features = false, features = ["read"] }
|
|
craft-docpath = { version = "0.1.0", git = "https://github.com/storytold/craft-libs", rev = "92d392cff132eaf53e13afff77f38b5c11b73aa0" }
|
|
craft-quit = { version = "0.1.0", git = "https://github.com/storytold/craft-libs", rev = "92d392cff132eaf53e13afff77f38b5c11b73aa0" }
|
|
craft-ecproj-format = { version = "0.1.0", git = "https://github.com/storytold/craft-libs", rev = "ca1b5e2edb8568335c6c14f390307bd5beae8238" }
|
|
# craft-update: app-specific pretend versions apply to startup and manual checks.
|
|
craft-update = { git = "https://github.com/storytold/craft-libs", version = "=0.1.0", rev = "c5a1cbfb5f9049f9270955caffb5bee5997aebf7", features = ["egui"] }
|
|
# internal
|
|
effectcraft-time = { path = "crates/time" }
|
|
effectcraft-geom = { path = "crates/geom" }
|
|
effectcraft-color = { path = "crates/color" }
|
|
effectcraft-raster = { path = "crates/raster" }
|
|
effectcraft-path = { path = "crates/path" }
|
|
effectcraft-keyframe = { path = "crates/keyframe" }
|
|
effectcraft-project = { path = "crates/project" }
|
|
effectcraft-text = { path = "crates/text" }
|
|
effectcraft-effects = { path = "crates/effects" }
|
|
effectcraft-track = { path = "crates/track" }
|
|
effectcraft-segment = { path = "crates/segment" }
|
|
effectcraft-sam2 = { path = "crates/sam2" }
|
|
effectcraft-model = { path = "crates/model" }
|
|
effectcraft-render = { path = "crates/render" }
|
|
effectcraft-gpu = { path = "crates/gpu" }
|
|
effectcraft-media = { path = "crates/media" }
|
|
effectcraft-export = { path = "crates/export" }
|
|
effectcraft-expr = { path = "crates/expr" }
|
|
effectcraft-lottie = { path = "crates/lottie" }
|
|
effectcraft-interchange = { path = "crates/interchange" }
|
|
effectcraft-pdf = { path = "crates/pdf" }
|
|
effectcraft-psd = { path = "crates/psd" }
|
|
effectcraft-aep = { path = "crates/aep" }
|
|
effectcraft-vp9enc = { path = "crates/vp9enc" }
|
|
effectcraft-svg = { path = "crates/svg" }
|
|
effectcraft-engine = { path = "crates/engine" }
|
|
effectcraft-host = { path = "crates/host" }
|
|
effectcraft-ui-egui = { path = "crates/ui-egui" }
|
|
effectcraft-automation = { path = "crates/automation" }
|
|
effectcraft-opusenc = { path = "crates/opusenc" }
|
|
effectcraft-script = { path = "crates/script" }
|
|
effectcraft-hevcenc = { path = "crates/hevcenc" }
|
|
effectcraft-av1enc = { path = "crates/av1enc" }
|
|
effectcraft-plugin = { path = "crates/plugin" }
|
|
effectcraft-helper-host = { path = "crates/helper-host" }
|
|
|
|
# foundation
|
|
thiserror = "2"
|
|
serde = { version = "1", features = ["derive", "rc"] }
|
|
serde_json = { version = "1", features = ["float_roundtrip"] }
|
|
log = "0.4"
|
|
# All date/time conversion goes through chrono (no hand-rolled calendar code beyond the 400-year range extension; AGENTS.md).
|
|
chrono = { version = "0.4.45", default-features = false, features = ["std"] }
|
|
rayon = "1"
|
|
# std::time::Instant/SystemTime on native; the browser clock on wasm32 (std's panic there).
|
|
web-time = "1"
|
|
gif = "0.14"
|
|
proptest = "1"
|
|
|
|
# scripting (expressions)
|
|
boa_engine = { version = "0.22", default-features = false }
|
|
# WebAssembly effect plug-ins (sandboxed interpreter; MIT/Apache-2.0, pure Rust)
|
|
wasmi = { version = "2", default-features = false, features = ["std", "validate", "wat", "deterministic", "portable-dispatch"] }
|
|
|
|
# geometry / fonts
|
|
kurbo = { version = "0.13", features = ["serde"] }
|
|
tiny-skia = { version = "0.12", default-features = false, features = ["std", "simd"] }
|
|
skrifa = { version = "0.44", default-features = false, features = ["std"] }
|
|
harfrust = { version = "0.12", default-features = false, features = ["std"] }
|
|
exr = "1.74"
|
|
image = { version = "0.25", default-features = false, features = ["png", "jpeg"] }
|
|
same-file = "1.0"
|
|
tempfile = "3.27"
|
|
|
|
# media codecs + containers: FilmCraft's pure-Rust crates, pinned to a revision (plan/adr/0001).
|
|
# Only `crates/media`, `crates/export` and `crates/interchange` may depend on these.
|
|
filmcraft-codecs = { git = "https://github.com/storytold/filmcraft", rev = "d5ead4ba1ee2f1cd13cb86a4239aee2730a3d9f5" }
|
|
filmcraft-media = { git = "https://github.com/storytold/filmcraft", rev = "d5ead4ba1ee2f1cd13cb86a4239aee2730a3d9f5" }
|
|
filmcraft-frame = { git = "https://github.com/storytold/filmcraft", rev = "d5ead4ba1ee2f1cd13cb86a4239aee2730a3d9f5" }
|
|
filmcraft-color = { git = "https://github.com/storytold/filmcraft", rev = "d5ead4ba1ee2f1cd13cb86a4239aee2730a3d9f5" }
|
|
filmcraft-time = { git = "https://github.com/storytold/filmcraft", rev = "d5ead4ba1ee2f1cd13cb86a4239aee2730a3d9f5" }
|
|
# encoders + muxer (crates/export)
|
|
filmcraft-h264enc = { git = "https://github.com/storytold/filmcraft", rev = "d5ead4ba1ee2f1cd13cb86a4239aee2730a3d9f5" }
|
|
filmcraft-prores = { git = "https://github.com/storytold/filmcraft", rev = "d5ead4ba1ee2f1cd13cb86a4239aee2730a3d9f5" }
|
|
filmcraft-aac = { git = "https://github.com/storytold/filmcraft", rev = "d5ead4ba1ee2f1cd13cb86a4239aee2730a3d9f5" }
|
|
filmcraft-isobmff = { git = "https://github.com/storytold/filmcraft", rev = "d5ead4ba1ee2f1cd13cb86a4239aee2730a3d9f5" }
|
|
# container headers read for AAC channel layouts (crates/media)
|
|
filmcraft-matroska = { git = "https://github.com/storytold/filmcraft", rev = "d5ead4ba1ee2f1cd13cb86a4239aee2730a3d9f5" }
|
|
filmcraft-mpegts = { git = "https://github.com/storytold/filmcraft", rev = "d5ead4ba1ee2f1cd13cb86a4239aee2730a3d9f5" }
|
|
# decoder used as the round-trip oracle of effectcraft-opusenc (crates/export dev-dependency)
|
|
filmcraft-opus = { git = "https://github.com/storytold/filmcraft", rev = "d5ead4ba1ee2f1cd13cb86a4239aee2730a3d9f5" }
|
|
filmcraft-vp9 = { git = "https://github.com/storytold/filmcraft", rev = "d5ead4ba1ee2f1cd13cb86a4239aee2730a3d9f5" }
|
|
# decoders used as the round-trip oracles of effectcraft-hevcenc / effectcraft-av1enc (dev-dependencies only)
|
|
filmcraft-hevc = { git = "https://github.com/storytold/filmcraft", rev = "d5ead4ba1ee2f1cd13cb86a4239aee2730a3d9f5" }
|
|
filmcraft-av1 = { git = "https://github.com/storytold/filmcraft", rev = "d5ead4ba1ee2f1cd13cb86a4239aee2730a3d9f5" }
|
|
# timeline interchange (EDL, FCP7 XML, FCPXML, OTIO) for Premiere Pro interop (crates/interchange only)
|
|
filmcraft-interchange = { git = "https://github.com/storytold/filmcraft", rev = "d5ead4ba1ee2f1cd13cb86a4239aee2730a3d9f5" }
|
|
filmcraft-project = { git = "https://github.com/storytold/filmcraft", rev = "d5ead4ba1ee2f1cd13cb86a4239aee2730a3d9f5" }
|
|
filmcraft-geom = { git = "https://github.com/storytold/filmcraft", rev = "d5ead4ba1ee2f1cd13cb86a4239aee2730a3d9f5" }
|
|
|
|
# gpu (the same wgpu eframe / egui-wgpu use)
|
|
wgpu = { version = "30.0.1", features = ["fragile-send-sync-non-atomic-wasm"] }
|
|
bytemuck = "1"
|
|
pollster = "1"
|
|
half = "2.7"
|
|
|
|
# ui
|
|
# Shared frontend components; keep this dependency above the engine boundary.
|
|
# Shared UI and the complete egui family select reviewed immutable commits below.
|
|
craft-ui = { version = "0.1.0", git = "https://github.com/storytold/craft-libs", rev = "92d392cff132eaf53e13afff77f38b5c11b73aa0", features = ["serde"] }
|
|
# `default_fonts` and `monochrome_emoji_fonts` are explicit: the app's `FontDefinitions::default()`
|
|
# and its `✔`/`▣` chrome glyphs need both, and kittest's own dev-dependencies do not propagate.
|
|
egui = { version = "0.37", default-features = false, features = ["default_fonts", "monochrome_emoji_fonts"] }
|
|
eframe = { version = "0.37", default-features = false }
|
|
# Resizable table columns (About ▸ Contributors / Models); no image loaders.
|
|
egui_extras = { version = "0.37", default-features = false }
|
|
egui_kittest = "0.37"
|
|
rfd = "0.17"
|
|
cpal = "0.16"
|
|
# The operating system's interface language (MIT/Apache-2.0, no dependencies on desktop).
|
|
sys-locale = "0.3"
|
|
|
|
# Local co-development against a FilmCraft checkout next to this repo: uncomment.
|
|
# [patch."https://github.com/storytold/filmcraft"]
|
|
# filmcraft-codecs = { path = "../filmcraft/crates/codecs" }
|
|
# filmcraft-media = { path = "../filmcraft/crates/media" }
|
|
# filmcraft-frame = { path = "../filmcraft/crates/frame" }
|
|
# filmcraft-color = { path = "../filmcraft/crates/color" }
|
|
# filmcraft-time = { path = "../filmcraft/crates/time" }
|
|
# filmcraft-h264enc = { path = "../filmcraft/crates/h264enc" }
|
|
# filmcraft-prores = { path = "../filmcraft/crates/prores" }
|
|
# filmcraft-aac = { path = "../filmcraft/crates/aac" }
|
|
# filmcraft-isobmff = { path = "../filmcraft/crates/isobmff" }
|
|
# filmcraft-matroska = { path = "../filmcraft/crates/matroska" }
|
|
# filmcraft-mpegts = { path = "../filmcraft/crates/mpegts" }
|
|
|
|
[workspace.lints.rust]
|
|
unsafe_code = "forbid"
|
|
|
|
[workspace.lints.clippy]
|
|
cognitive_complexity = "deny"
|
|
too_many_arguments = "deny"
|
|
wildcard_imports = "deny"
|
|
dbg_macro = "warn"
|
|
todo = "warn"
|
|
needless_range_loop = "allow"
|
|
type_complexity = "allow"
|
|
|
|
[profile.dev.package."*"]
|
|
opt-level = 2
|
|
debug = false
|
|
|
|
[profile.dev]
|
|
opt-level = 1
|
|
# Panics and backtraces keep file and line; full debug info only made the many test binaries large.
|
|
debug = "line-tables-only"
|
|
|
|
# Same settings as `dev`, but with full debug info for interactive debugger sessions: local
|
|
# variables, parameters and column breakpoints work. Use `--profile dev-full` when debugging;
|
|
# everything else stays on the fast default. See CONTRIBUTING.md, "Setup".
|
|
[profile.dev-full]
|
|
inherits = "dev"
|
|
debug = true
|
|
|
|
# Pixel hot loops: keep debug builds interactive.
|
|
[profile.dev.package.effectcraft-raster]
|
|
opt-level = 3
|
|
|
|
[profile.dev.package.effectcraft-render]
|
|
opt-level = 3
|
|
|
|
[profile.dev.package.effectcraft-gpu]
|
|
opt-level = 3
|
|
|
|
[profile.dev.package.effectcraft-effects]
|
|
opt-level = 3
|
|
|
|
[profile.dev.package.effectcraft-track]
|
|
opt-level = 3
|
|
|
|
[profile.dev.package.effectcraft-path]
|
|
opt-level = 3
|
|
|
|
[profile.dev.package.effectcraft-media]
|
|
opt-level = 3
|
|
|
|
[profile.dev.package.effectcraft-opusenc]
|
|
opt-level = 3
|
|
|
|
[profile.dev.package.effectcraft-export]
|
|
opt-level = 3
|
|
|
|
[profile.dev.package.effectcraft-vp9enc]
|
|
opt-level = 3
|
|
|
|
[profile.dev.package.effectcraft-hevcenc]
|
|
opt-level = 3
|
|
|
|
[profile.dev.package.effectcraft-av1enc]
|
|
opt-level = 3
|
|
|
|
# FilmCraft codec hot loops (same settings as FilmCraft's own workspace).
|
|
[profile.dev.package.filmcraft-h264]
|
|
opt-level = 3
|
|
|
|
[profile.dev.package.filmcraft-h264enc]
|
|
opt-level = 3
|
|
|
|
[profile.dev.package.filmcraft-hevc]
|
|
opt-level = 3
|
|
|
|
[profile.dev.package.filmcraft-vp9]
|
|
opt-level = 3
|
|
|
|
[profile.dev.package.filmcraft-prores]
|
|
opt-level = 3
|
|
|
|
[profile.dev.package.filmcraft-dnx]
|
|
opt-level = 3
|
|
|
|
[profile.dev.package.filmcraft-av1]
|
|
opt-level = 3
|
|
|
|
[profile.dev.package.filmcraft-aac]
|
|
opt-level = 3
|
|
|
|
[profile.dev.package.filmcraft-opus]
|
|
opt-level = 3
|
|
|
|
[profile.release]
|
|
lto = "thin"
|
|
codegen-units = 1
|
|
|
|
[patch.crates-io]
|
|
hayro-syntax = { git = "https://github.com/storytold/craft-libs", rev = "92d392cff132eaf53e13afff77f38b5c11b73aa0", version = "=0.7.2" }
|
|
hayro-jbig2 = { git = "https://github.com/storytold/craft-libs", rev = "92d392cff132eaf53e13afff77f38b5c11b73aa0", version = "=0.3.0" }
|
|
ecolor = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
|
|
emath = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
|
|
epaint = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
|
|
epaint_default_fonts = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
|
|
egui = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
|
|
egui-winit = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
|
|
egui-wgpu = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
|
|
egui_glow = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
|
|
egui_extras = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
|
|
egui_kittest = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
|
|
egui_system_font_provider = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
|
|
eframe = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
|
|
egui_demo_lib = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
|
|
egui_inspection = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
|
|
winit = { git = "https://github.com/storytold/winit.git", rev = "a517b3846ee8457d84ee4975110bfda6797c44dc" }
|