diff --git a/CHANGELOG.md b/CHANGELOG.md index 46df27ac..6d3af875 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,9 @@ instead of `&[f32]`. This is more flexible for gradient evaluation, because it allows the caller to specify up to three gradients, without pinning them to specific argument. +- Moved `tile_sizes_2d`, `tile_sizes_3d`, and `simplify_tree_during_meshing` + into a new `fidget::shape::RenderHits` trait. This is a building block for + generic (_n_-variable) function evaluation. # 0.2.6 This is a relatively small release; there are a few features to improve the diff --git a/demo/src/main.rs b/demo/src/main.rs index 8c552b32..b037fdd7 100644 --- a/demo/src/main.rs +++ b/demo/src/main.rs @@ -112,7 +112,7 @@ struct MeshSettings { } //////////////////////////////////////////////////////////////////////////////// -fn run3d( +fn run3d( shape: S, settings: &ImageSettings, isometric: bool, @@ -168,7 +168,7 @@ fn run3d( //////////////////////////////////////////////////////////////////////////////// -fn run2d( +fn run2d( shape: S, settings: &ImageSettings, brute: bool, @@ -236,10 +236,13 @@ fn run2d( //////////////////////////////////////////////////////////////////////////////// -fn run_mesh( +fn run_mesh( shape: S, settings: &MeshSettings, -) -> fidget::mesh::Mesh { +) -> fidget::mesh::Mesh +where + ::TransformedShape: fidget::shape::RenderHints, +{ let mut mesh = fidget::mesh::Mesh::new(); for _ in 0..settings.n { diff --git a/fidget/benches/render.rs b/fidget/benches/render.rs index a0e2cdce..204d46c1 100644 --- a/fidget/benches/render.rs +++ b/fidget/benches/render.rs @@ -4,7 +4,7 @@ use criterion::{ const PROSPERO: &str = include_str!("../../models/prospero.vm"); -use fidget::eval::{MathShape, Shape}; +use fidget::{eval::MathShape, shape::RenderHints}; pub fn prospero_size_sweep(c: &mut Criterion) { let (ctx, root) = fidget::Context::from_text(PROSPERO.as_bytes()).unwrap(); diff --git a/fidget/src/core/eval/mod.rs b/fidget/src/core/eval/mod.rs index a7a7d136..1a10b1a1 100644 --- a/fidget/src/core/eval/mod.rs +++ b/fidget/src/core/eval/mod.rs @@ -157,22 +157,6 @@ pub trait Shape: Send + Sync + Clone { /// shapes, it's typically the length of the tape, fn size(&self) -> usize; - /// Recommended tile sizes for 3D rendering - fn tile_sizes_3d() -> &'static [usize]; - - /// Recommended tile sizes for 2D rendering - fn tile_sizes_2d() -> &'static [usize]; - - /// Indicates whether we run tape simplification at the given cell depth - /// during meshing. - /// - /// By default, this is always true; for evaluators where simplification is - /// more expensive than evaluation (i.e. the JIT), it may only be true at - /// certain depths. - fn simplify_tree_during_meshing(_d: usize) -> bool { - true - } - /// Associated type returned when applying a transform /// /// This is normally [`TransformedShape`](TransformedShape), but if diff --git a/fidget/src/core/eval/transform.rs b/fidget/src/core/eval/transform.rs index 882cf71d..d5684b61 100644 --- a/fidget/src/core/eval/transform.rs +++ b/fidget/src/core/eval/transform.rs @@ -1,5 +1,6 @@ use crate::{ eval::{BulkEvaluator, Grad, Interval, Shape, Tape, TracingEvaluator}, + shape::RenderHints, Error, }; use nalgebra::{Matrix4, Point3, Vector3}; @@ -190,12 +191,6 @@ impl Shape for TransformedShape { type IntervalEval = TransformedTracingEval<::IntervalEval>; type FloatSliceEval = TransformedBulkEval<::FloatSliceEval>; type GradSliceEval = TransformedBulkEval<::GradSliceEval>; - fn tile_sizes_2d() -> &'static [usize] { - S::tile_sizes_2d() - } - fn tile_sizes_3d() -> &'static [usize] { - S::tile_sizes_3d() - } fn size(&self) -> usize { self.shape.size() } @@ -261,3 +256,12 @@ impl Shape for TransformedShape { self } } + +impl RenderHints for TransformedShape { + fn tile_sizes_2d() -> &'static [usize] { + S::tile_sizes_2d() + } + fn tile_sizes_3d() -> &'static [usize] { + S::tile_sizes_3d() + } +} diff --git a/fidget/src/core/shape/mod.rs b/fidget/src/core/shape/mod.rs index 6d86a1dd..eb602598 100644 --- a/fidget/src/core/shape/mod.rs +++ b/fidget/src/core/shape/mod.rs @@ -1,3 +1,22 @@ //! Shape-specific data types mod bounds; pub use bounds::Bounds; + +/// Hints for how to render this particular type +pub trait RenderHints { + /// Recommended tile sizes for 3D rendering + fn tile_sizes_3d() -> &'static [usize]; + + /// Recommended tile sizes for 2D rendering + fn tile_sizes_2d() -> &'static [usize]; + + /// Indicates whether we run tape simplification at the given cell depth + /// during meshing. + /// + /// By default, this is always true; for evaluators where simplification is + /// more expensive than evaluation (i.e. the JIT), it may only be true at + /// certain depths. + fn simplify_tree_during_meshing(_d: usize) -> bool { + true + } +} diff --git a/fidget/src/core/vm/mod.rs b/fidget/src/core/vm/mod.rs index c37a7a83..78f54fb7 100644 --- a/fidget/src/core/vm/mod.rs +++ b/fidget/src/core/vm/mod.rs @@ -6,6 +6,7 @@ use crate::{ BulkEvaluator, MathShape, Shape, Tape, Trace, TracingEvaluator, TransformedShape, }, + shape::RenderHints, types::{Grad, Interval}, Context, Error, }; @@ -176,6 +177,13 @@ impl Shape for GenericVmShape { GenericVmShape::size(self) } + type TransformedShape = TransformedShape; + fn apply_transform(self, mat: Matrix4) -> Self::TransformedShape { + TransformedShape::new(self, mat) + } +} + +impl RenderHints for GenericVmShape { fn tile_sizes_3d() -> &'static [usize] { &[256, 128, 64, 32, 16, 8] } @@ -183,11 +191,6 @@ impl Shape for GenericVmShape { fn tile_sizes_2d() -> &'static [usize] { &[256, 128, 64, 32, 16, 8] } - - type TransformedShape = TransformedShape; - fn apply_transform(self, mat: Matrix4) -> Self::TransformedShape { - TransformedShape::new(self, mat) - } } impl MathShape for GenericVmShape { diff --git a/fidget/src/jit/mod.rs b/fidget/src/jit/mod.rs index 4424d1e4..c183b730 100644 --- a/fidget/src/jit/mod.rs +++ b/fidget/src/jit/mod.rs @@ -31,6 +31,7 @@ use crate::{ TransformedShape, }, jit::mmap::Mmap, + shape::RenderHints, types::{Grad, Interval}, vm::{Choice, GenericVmShape, VmData, VmTrace, VmWorkspace}, Error, @@ -898,6 +899,17 @@ impl Shape for JitShape { self.0.recycle() } + fn size(&self) -> usize { + self.0.size() + } + + type TransformedShape = TransformedShape; + fn apply_transform(self, mat: Matrix4) -> Self::TransformedShape { + TransformedShape::new(self, mat) + } +} + +impl RenderHints for JitShape { fn tile_sizes_3d() -> &'static [usize] { &[64, 16, 8] } @@ -910,15 +922,6 @@ impl Shape for JitShape { // Unscientifically selected, but similar to tile_sizes_3d d % 8 == 4 } - - fn size(&self) -> usize { - self.0.size() - } - - type TransformedShape = TransformedShape; - fn apply_transform(self, mat: Matrix4) -> Self::TransformedShape { - TransformedShape::new(self, mat) - } } //////////////////////////////////////////////////////////////////////////////// diff --git a/fidget/src/mesh/mt/octree.rs b/fidget/src/mesh/mt/octree.rs index e3174df1..e5e1631f 100644 --- a/fidget/src/mesh/mt/octree.rs +++ b/fidget/src/mesh/mt/octree.rs @@ -8,6 +8,7 @@ use crate::{ types::Corner, Octree, Settings, }, + shape::RenderHints, }; use std::sync::{mpsc::TryRecvError, Arc}; @@ -88,7 +89,7 @@ struct Done { completed_by: usize, } -pub struct OctreeWorker { +pub struct OctreeWorker { /// Global index of this worker thread /// /// For example, this is the thread's own index in `friend_queue` and @@ -116,7 +117,7 @@ pub struct OctreeWorker { friend_done: Vec>>, } -impl OctreeWorker { +impl OctreeWorker { pub fn scheduler(eval: Arc>, settings: Settings) -> Octree { let task_queues = QueuePool::new(settings.threads()); let done_queues = std::iter::repeat_with(std::sync::mpsc::channel) diff --git a/fidget/src/mesh/octree.rs b/fidget/src/mesh/octree.rs index 4fcdcd35..0aca834e 100644 --- a/fidget/src/mesh/octree.rs +++ b/fidget/src/mesh/octree.rs @@ -12,6 +12,7 @@ use super::{ }; use crate::{ eval::{BulkEvaluator, Shape, Tape, TracingEvaluator}, + shape::RenderHints, types::Grad, }; use std::{num::NonZeroUsize, sync::Arc, sync::OnceLock}; @@ -90,7 +91,13 @@ impl Octree { /// Builds an octree to the given depth /// /// The shape is evaluated on the region specified by `settings.bounds`. - pub fn build(shape: &S, settings: Settings) -> Self { + pub fn build( + shape: &S, + settings: Settings, + ) -> Self + where + ::TransformedShape: RenderHints, + { // Transform the shape given our bounds let t = settings.bounds.transform(); if t == nalgebra::Transform::identity() { @@ -109,7 +116,10 @@ impl Octree { } } - fn build_inner(shape: &S, settings: Settings) -> Self { + fn build_inner( + shape: &S, + settings: Settings, + ) -> Self { let eval = Arc::new(EvalGroup::new(shape.clone())); if settings.threads() == 1 { @@ -228,7 +238,7 @@ impl std::ops::IndexMut for Octree { /// Data structure for an under-construction octree #[derive(Debug)] -pub(crate) struct OctreeBuilder { +pub(crate) struct OctreeBuilder { /// Internal octree /// /// Note that in this internal octree, the `index` field of leaf nodes @@ -261,13 +271,13 @@ pub(crate) struct OctreeBuilder { workspace: S::Workspace, } -impl Default for OctreeBuilder { +impl Default for OctreeBuilder { fn default() -> Self { Self::new() } } -impl From> for Octree { +impl From> for Octree { fn from(o: OctreeBuilder) -> Self { // Convert from "leaf index into self.leafs" (in the builder) to // "leaf index into self.verts" (in the resulting Octree) @@ -293,7 +303,7 @@ impl From> for Octree { } } -impl OctreeBuilder { +impl OctreeBuilder { /// Builds a new octree, which allocates data for 8 root cells pub(crate) fn new() -> Self { Self { @@ -903,7 +913,7 @@ impl OctreeBuilder { /// `OctreeBuilder` functions which are only used during multithreaded rendering #[cfg(not(target_arch = "wasm32"))] -impl OctreeBuilder { +impl OctreeBuilder { /// Builds a new empty octree /// /// This still allocates data to reserve the lowest slot in `hermite` diff --git a/models/foo.vm b/models/foo.vm new file mode 100644 index 00000000..0621f77b --- /dev/null +++ b/models/foo.vm @@ -0,0 +1,8 @@ +X var-x +Y var-y +X2 square X +Y2 square Y +out add X2 Y2 +s sqrt out +one const 0.1 +foo sub s one diff --git a/viewer/src/main.rs b/viewer/src/main.rs index f8e1841b..95f0aaba 100644 --- a/viewer/src/main.rs +++ b/viewer/src/main.rs @@ -82,7 +82,9 @@ fn render_thread( wake: Sender<()>, ) -> Result<()> where - S: fidget::eval::Shape + fidget::eval::MathShape, + S: fidget::eval::Shape + + fidget::eval::MathShape + + fidget::shape::RenderHints, { let mut config = None; let mut script_ctx = None; @@ -148,7 +150,7 @@ where } } -fn render( +fn render( mode: &RenderMode, shape: S, image_size: usize,