Skip to content

Commit

Permalink
Move render hints into dedicated trait (#108)
Browse files Browse the repository at this point in the history
  • Loading branch information
mkeeter authored May 18, 2024
1 parent a3ef12e commit 3a83eb1
Show file tree
Hide file tree
Showing 12 changed files with 92 additions and 52 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 7 additions & 4 deletions demo/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ struct MeshSettings {
}

////////////////////////////////////////////////////////////////////////////////
fn run3d<S: fidget::eval::Shape>(
fn run3d<S: fidget::eval::Shape + fidget::shape::RenderHints>(
shape: S,
settings: &ImageSettings,
isometric: bool,
Expand Down Expand Up @@ -168,7 +168,7 @@ fn run3d<S: fidget::eval::Shape>(

////////////////////////////////////////////////////////////////////////////////

fn run2d<S: fidget::eval::Shape>(
fn run2d<S: fidget::eval::Shape + fidget::shape::RenderHints>(
shape: S,
settings: &ImageSettings,
brute: bool,
Expand Down Expand Up @@ -236,10 +236,13 @@ fn run2d<S: fidget::eval::Shape>(

////////////////////////////////////////////////////////////////////////////////

fn run_mesh<S: fidget::eval::Shape>(
fn run_mesh<S: fidget::eval::Shape + fidget::shape::RenderHints>(
shape: S,
settings: &MeshSettings,
) -> fidget::mesh::Mesh {
) -> fidget::mesh::Mesh
where
<S as fidget::eval::Shape>::TransformedShape: fidget::shape::RenderHints,
{
let mut mesh = fidget::mesh::Mesh::new();

for _ in 0..settings.n {
Expand Down
2 changes: 1 addition & 1 deletion fidget/benches/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
16 changes: 0 additions & 16 deletions fidget/src/core/eval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Self>`](TransformedShape), but if
Expand Down
16 changes: 10 additions & 6 deletions fidget/src/core/eval/transform.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{
eval::{BulkEvaluator, Grad, Interval, Shape, Tape, TracingEvaluator},
shape::RenderHints,
Error,
};
use nalgebra::{Matrix4, Point3, Vector3};
Expand Down Expand Up @@ -190,12 +191,6 @@ impl<S: Shape> Shape for TransformedShape<S> {
type IntervalEval = TransformedTracingEval<<S as Shape>::IntervalEval>;
type FloatSliceEval = TransformedBulkEval<<S as Shape>::FloatSliceEval>;
type GradSliceEval = TransformedBulkEval<<S as Shape>::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()
}
Expand Down Expand Up @@ -261,3 +256,12 @@ impl<S: Shape> Shape for TransformedShape<S> {
self
}
}

impl<S: RenderHints> RenderHints for TransformedShape<S> {
fn tile_sizes_2d() -> &'static [usize] {
S::tile_sizes_2d()
}
fn tile_sizes_3d() -> &'static [usize] {
S::tile_sizes_3d()
}
}
19 changes: 19 additions & 0 deletions fidget/src/core/shape/mod.rs
Original file line number Diff line number Diff line change
@@ -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
}
}
13 changes: 8 additions & 5 deletions fidget/src/core/vm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::{
BulkEvaluator, MathShape, Shape, Tape, Trace, TracingEvaluator,
TransformedShape,
},
shape::RenderHints,
types::{Grad, Interval},
Context, Error,
};
Expand Down Expand Up @@ -176,18 +177,20 @@ impl<const N: usize> Shape for GenericVmShape<N> {
GenericVmShape::size(self)
}

type TransformedShape = TransformedShape<Self>;
fn apply_transform(self, mat: Matrix4<f32>) -> Self::TransformedShape {
TransformedShape::new(self, mat)
}
}

impl<const N: usize> RenderHints for GenericVmShape<N> {
fn tile_sizes_3d() -> &'static [usize] {
&[256, 128, 64, 32, 16, 8]
}

fn tile_sizes_2d() -> &'static [usize] {
&[256, 128, 64, 32, 16, 8]
}

type TransformedShape = TransformedShape<Self>;
fn apply_transform(self, mat: Matrix4<f32>) -> Self::TransformedShape {
TransformedShape::new(self, mat)
}
}

impl<const N: usize> MathShape for GenericVmShape<N> {
Expand Down
21 changes: 12 additions & 9 deletions fidget/src/jit/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use crate::{
TransformedShape,
},
jit::mmap::Mmap,
shape::RenderHints,
types::{Grad, Interval},
vm::{Choice, GenericVmShape, VmData, VmTrace, VmWorkspace},
Error,
Expand Down Expand Up @@ -898,6 +899,17 @@ impl Shape for JitShape {
self.0.recycle()
}

fn size(&self) -> usize {
self.0.size()
}

type TransformedShape = TransformedShape<Self>;
fn apply_transform(self, mat: Matrix4<f32>) -> Self::TransformedShape {
TransformedShape::new(self, mat)
}
}

impl RenderHints for JitShape {
fn tile_sizes_3d() -> &'static [usize] {
&[64, 16, 8]
}
Expand All @@ -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<Self>;
fn apply_transform(self, mat: Matrix4<f32>) -> Self::TransformedShape {
TransformedShape::new(self, mat)
}
}

////////////////////////////////////////////////////////////////////////////////
Expand Down
5 changes: 3 additions & 2 deletions fidget/src/mesh/mt/octree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::{
types::Corner,
Octree, Settings,
},
shape::RenderHints,
};
use std::sync::{mpsc::TryRecvError, Arc};

Expand Down Expand Up @@ -88,7 +89,7 @@ struct Done<S: Shape> {
completed_by: usize,
}

pub struct OctreeWorker<S: Shape> {
pub struct OctreeWorker<S: Shape + RenderHints> {
/// Global index of this worker thread
///
/// For example, this is the thread's own index in `friend_queue` and
Expand Down Expand Up @@ -116,7 +117,7 @@ pub struct OctreeWorker<S: Shape> {
friend_done: Vec<std::sync::mpsc::Sender<Done<S>>>,
}

impl<S: Shape> OctreeWorker<S> {
impl<S: Shape + RenderHints> OctreeWorker<S> {
pub fn scheduler(eval: Arc<EvalGroup<S>>, settings: Settings) -> Octree {
let task_queues = QueuePool::new(settings.threads());
let done_queues = std::iter::repeat_with(std::sync::mpsc::channel)
Expand Down
24 changes: 17 additions & 7 deletions fidget/src/mesh/octree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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<S: Shape + Clone>(shape: &S, settings: Settings) -> Self {
pub fn build<S: Shape + RenderHints + Clone>(
shape: &S,
settings: Settings,
) -> Self
where
<S as Shape>::TransformedShape: RenderHints,
{
// Transform the shape given our bounds
let t = settings.bounds.transform();
if t == nalgebra::Transform::identity() {
Expand All @@ -109,7 +116,10 @@ impl Octree {
}
}

fn build_inner<S: Shape + Clone>(shape: &S, settings: Settings) -> Self {
fn build_inner<S: Shape + RenderHints + Clone>(
shape: &S,
settings: Settings,
) -> Self {
let eval = Arc::new(EvalGroup::new(shape.clone()));

if settings.threads() == 1 {
Expand Down Expand Up @@ -228,7 +238,7 @@ impl std::ops::IndexMut<CellIndex> for Octree {

/// Data structure for an under-construction octree
#[derive(Debug)]
pub(crate) struct OctreeBuilder<S: Shape> {
pub(crate) struct OctreeBuilder<S: Shape + RenderHints> {
/// Internal octree
///
/// Note that in this internal octree, the `index` field of leaf nodes
Expand Down Expand Up @@ -261,13 +271,13 @@ pub(crate) struct OctreeBuilder<S: Shape> {
workspace: S::Workspace,
}

impl<S: Shape> Default for OctreeBuilder<S> {
impl<S: Shape + RenderHints> Default for OctreeBuilder<S> {
fn default() -> Self {
Self::new()
}
}

impl<S: Shape> From<OctreeBuilder<S>> for Octree {
impl<S: Shape + RenderHints> From<OctreeBuilder<S>> for Octree {
fn from(o: OctreeBuilder<S>) -> Self {
// Convert from "leaf index into self.leafs" (in the builder) to
// "leaf index into self.verts" (in the resulting Octree)
Expand All @@ -293,7 +303,7 @@ impl<S: Shape> From<OctreeBuilder<S>> for Octree {
}
}

impl<S: Shape> OctreeBuilder<S> {
impl<S: Shape + RenderHints> OctreeBuilder<S> {
/// Builds a new octree, which allocates data for 8 root cells
pub(crate) fn new() -> Self {
Self {
Expand Down Expand Up @@ -903,7 +913,7 @@ impl<S: Shape> OctreeBuilder<S> {

/// `OctreeBuilder` functions which are only used during multithreaded rendering
#[cfg(not(target_arch = "wasm32"))]
impl<S: Shape> OctreeBuilder<S> {
impl<S: Shape + RenderHints> OctreeBuilder<S> {
/// Builds a new empty octree
///
/// This still allocates data to reserve the lowest slot in `hermite`
Expand Down
8 changes: 8 additions & 0 deletions models/foo.vm
Original file line number Diff line number Diff line change
@@ -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
6 changes: 4 additions & 2 deletions viewer/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ fn render_thread<S>(
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;
Expand Down Expand Up @@ -148,7 +150,7 @@ where
}
}

fn render<S: fidget::eval::Shape>(
fn render<S: fidget::eval::Shape + fidget::shape::RenderHints>(
mode: &RenderMode,
shape: S,
image_size: usize,
Expand Down

0 comments on commit 3a83eb1

Please sign in to comment.