Skip to content

Commit

Permalink
Give up on const generics; use separate types for 2D and 3D stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
mkeeter committed Nov 15, 2024
1 parent b3f6d28 commit 8c00f62
Show file tree
Hide file tree
Showing 17 changed files with 504 additions and 590 deletions.
10 changes: 5 additions & 5 deletions demos/cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,10 @@ fn run3d<F: fidget::eval::Function + fidget::shape::RenderHints>(
if !isometric {
*mat.matrix_mut().get_mut((3, 2)).unwrap() = 0.3;
}
let cfg = fidget::render::RenderConfig {
let cfg = fidget::render::VoxelRenderConfig {
image_size: fidget::render::VoxelSize::from(settings.size),
tile_sizes: F::tile_sizes_3d(),
threads: settings.threads,
threads: settings.threads.into(),
..Default::default()
};
let shape = shape.apply_transform(mat.into());
Expand Down Expand Up @@ -197,10 +197,10 @@ fn run2d<F: fidget::eval::Function + fidget::shape::RenderHints>(
.flat_map(|i| i.into_iter())
.collect()
} else {
let cfg = fidget::render::RenderConfig {
let cfg = fidget::render::ImageRenderConfig {
image_size: fidget::render::ImageSize::from(settings.size),
tile_sizes: F::tile_sizes_2d(),
threads: settings.threads,
threads: settings.threads.into(),
..Default::default()
};
if sdf {
Expand Down Expand Up @@ -241,7 +241,7 @@ fn run_mesh<F: fidget::eval::Function + fidget::shape::RenderHints>(

for _ in 0..settings.n {
let settings = fidget::mesh::Settings {
threads: settings.threads,
threads: settings.threads.into(),
depth: settings.depth,
..Default::default()
};
Expand Down
41 changes: 19 additions & 22 deletions demos/viewer/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ use clap::Parser;
use crossbeam_channel::{unbounded, Receiver, Sender};
use eframe::egui;
use env_logger::Env;
use fidget::render::RenderConfig;
use log::{debug, error, info, warn};
use nalgebra::{Point2, Vector3};
use notify::Watcher;

use fidget::render::{ImageRenderConfig, View2, View3, VoxelRenderConfig};

use std::{error::Error, path::Path};

/// Minimal viewer, using Fidget to render a Rhai script
Expand Down Expand Up @@ -161,12 +162,12 @@ fn render<F: fidget::eval::Function + fidget::shape::RenderHints>(
pixels: &mut [egui::Color32],
) {
match mode {
RenderMode::TwoD { camera, mode, .. } => {
let config = RenderConfig {
RenderMode::TwoD { view, mode, .. } => {
let config = ImageRenderConfig {
image_size,
tile_sizes: F::tile_sizes_2d(),
camera: *camera,
..RenderConfig::default()
view: *view,
..Default::default()
};

match mode {
Expand Down Expand Up @@ -212,18 +213,18 @@ fn render<F: fidget::eval::Function + fidget::shape::RenderHints>(
}
RenderMode::ThreeD(camera, mode) => {
// XXX allow selection of depth?
let config = RenderConfig {
let config = VoxelRenderConfig {
image_size: fidget::render::VoxelSize::new(
image_size.width(),
image_size.height(),
512,
),
tile_sizes: F::tile_sizes_3d(),
camera: fidget::render::Camera::from_center_and_scale(
view: View3::from_center_and_scale(
Vector3::new(camera.offset.x, camera.offset.y, 0.0),
camera.scale,
),
..RenderConfig::default()
..Default::default()
};
let (depth, color) = fidget::render::render3d(shape, &config);
match mode {
Expand Down Expand Up @@ -387,7 +388,7 @@ enum ThreeDMode {
#[derive(Copy, Clone)]
enum RenderMode {
TwoD {
camera: fidget::render::Camera<2>,
view: View2,

/// Drag start position (in model coordinates)
drag_start: Option<Point2<f32>>,
Expand All @@ -407,7 +408,7 @@ impl RenderMode {
RenderMode::ThreeD(..) => {
*self = RenderMode::TwoD {
// TODO get parameters from 3D camera here?
camera: fidget::render::Camera::default(),
view: Default::default(),
drag_start: None,
mode: new_mode,
};
Expand Down Expand Up @@ -465,7 +466,7 @@ impl ViewerApp {
image_rx,

mode: RenderMode::TwoD {
camera: fidget::render::Camera::default(),
view: Default::default(),
drag_start: None,
mode: Mode2D::Color,
},
Expand Down Expand Up @@ -662,19 +663,18 @@ impl eframe::App for ViewerApp {
// Handle pan and zoom
match &mut self.mode {
RenderMode::TwoD {
camera, drag_start, ..
view, drag_start, ..
} => {
let image_size = fidget::render::ImageSize::new(
rect.width() as u32,
rect.height() as u32,
);

let mat = view.world_to_model() * image_size.screen_to_world();
if let Some(pos) = r.interact_pointer_pos() {
let mat =
camera.world_to_model() * image_size.screen_to_world();
let pos = mat.transform_point(&Point2::new(pos.x, pos.y));
if let Some(prev) = *drag_start {
camera.translate(prev - pos);
view.translate(prev - pos);
render_changed |= prev != pos;
} else {
*drag_start = Some(pos);
Expand All @@ -685,14 +685,11 @@ impl eframe::App for ViewerApp {

if r.hovered() {
let scroll = ctx.input(|i| i.smooth_scroll_delta.y);
let mouse_pos =
ctx.input(|i| i.pointer.hover_pos()).map(|p| {
image_size
.screen_to_world()
.transform_point(&Point2::new(p.x, p.y))
});
let mouse_pos = ctx
.input(|i| i.pointer.hover_pos())
.map(|p| mat.transform_point(&Point2::new(p.x, p.y)));
if scroll != 0.0 {
camera.zoom((scroll / 100.0).exp2(), mouse_pos);
view.zoom((scroll / 100.0).exp2(), mouse_pos);
render_changed = true;
}
}
Expand Down
17 changes: 10 additions & 7 deletions fidget/benches/mesh.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use criterion::{
black_box, criterion_group, criterion_main, BenchmarkId, Criterion,
};
use fidget::render::ThreadCount;

const COLONNADE: &str = include_str!("../../models/colonnade.vm");

Expand All @@ -12,12 +13,15 @@ pub fn colonnade_octree_thread_sweep(c: &mut Criterion) {

let mut group =
c.benchmark_group("speed vs threads (colonnade, octree) (depth 6)");
for threads in [1, 4, 8] {
for threads in std::iter::once(ThreadCount::One)
.chain([1, 4, 8].map(|i| ThreadCount::Many(i.try_into().unwrap())))
{
let cfg = &fidget::mesh::Settings {
depth: 6,
threads: threads.try_into().unwrap(),
threads,
..Default::default()
};

#[cfg(feature = "jit")]
group.bench_function(BenchmarkId::new("jit", threads), move |b| {
b.iter(|| {
Expand Down Expand Up @@ -45,11 +49,10 @@ pub fn colonnade_mesh(c: &mut Criterion) {

let mut group =
c.benchmark_group("speed vs threads (colonnade, meshing) (depth 8)");
for threads in [1, 4, 8] {
let cfg = &fidget::mesh::Settings {
threads: threads.try_into().unwrap(),
..cfg
};
for threads in std::iter::once(ThreadCount::One)
.chain([1, 4, 8].map(|i| ThreadCount::Many(i.try_into().unwrap())))
{
let cfg = &fidget::mesh::Settings { threads, ..cfg };
group.bench_function(
BenchmarkId::new("walk_dual", threads),
move |b| {
Expand Down
21 changes: 13 additions & 8 deletions fidget/benches/render.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use criterion::{
black_box, criterion_group, criterion_main, BenchmarkId, Criterion,
};
use fidget::{render::ImageSize, shape::RenderHints};
use fidget::{
render::{ImageSize, ThreadCount},
shape::RenderHints,
};

const PROSPERO: &str = include_str!("../../models/prospero.vm");

Expand All @@ -15,7 +18,7 @@ pub fn prospero_size_sweep(c: &mut Criterion) {
let mut group =
c.benchmark_group("speed vs image size (prospero, 2d) (8 threads)");
for size in [256, 512, 768, 1024, 1280, 1546, 1792, 2048] {
let cfg = &fidget::render::RenderConfig {
let cfg = &fidget::render::ImageRenderConfig {
image_size: fidget::render::ImageSize::from(size),
tile_sizes: fidget::vm::VmFunction::tile_sizes_2d(),
..Default::default()
Expand All @@ -32,7 +35,7 @@ pub fn prospero_size_sweep(c: &mut Criterion) {

#[cfg(feature = "jit")]
{
let cfg = &fidget::render::RenderConfig {
let cfg = &fidget::render::ImageRenderConfig {
image_size: fidget::render::ImageSize::from(size),
tile_sizes: fidget::jit::JitFunction::tile_sizes_2d(),
..Default::default()
Expand All @@ -59,11 +62,13 @@ pub fn prospero_thread_sweep(c: &mut Criterion) {

let mut group =
c.benchmark_group("speed vs threads (prospero, 2d) (1024 x 1024)");
for threads in [1, 2, 4, 8, 16] {
let cfg = &fidget::render::RenderConfig {
for threads in std::iter::once(ThreadCount::One).chain(
[1, 2, 4, 8, 16].map(|i| ThreadCount::Many(i.try_into().unwrap())),
) {
let cfg = &fidget::render::ImageRenderConfig {
image_size: ImageSize::from(1024),
tile_sizes: fidget::vm::VmFunction::tile_sizes_2d(),
threads: threads.try_into().unwrap(),
threads,
..Default::default()
};
group.bench_function(BenchmarkId::new("vm", threads), move |b| {
Expand All @@ -77,10 +82,10 @@ pub fn prospero_thread_sweep(c: &mut Criterion) {
});
#[cfg(feature = "jit")]
{
let cfg = &fidget::render::RenderConfig {
let cfg = &fidget::render::ImageRenderConfig {
image_size: ImageSize::from(1024),
tile_sizes: fidget::jit::JitFunction::tile_sizes_2d(),
threads: threads.try_into().unwrap(),
threads,
..Default::default()
};
group.bench_function(BenchmarkId::new("jit", threads), move |b| {
Expand Down
16 changes: 15 additions & 1 deletion fidget/src/core/shape/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use crate::{
var::{Var, VarIndex, VarMap},
Error,
};
use nalgebra::{Matrix4, Point3};
use nalgebra::{Matrix4, Point2, Point3};
use std::collections::HashMap;

/// A shape represents an implicit surface
Expand Down Expand Up @@ -333,6 +333,20 @@ impl TileSizes {
pub fn get(&self, i: usize) -> Option<usize> {
self.0.get(i).copied()
}

/// Returns the data offset of a global pixel position within a root tile
///
/// The root tile is implicit: it's set by the largest tile size and aligned
/// to multiples of that size.
#[inline]
pub(crate) fn pixel_offset(&self, pos: Point2<usize>) -> usize {
// Find the relative position within the root tile
let x = pos.x % self.0[0];
let y = pos.y % self.0[0];

// Apply the relative offset and find the data index
x + y * self.0[0]
}
}

/// Hints for how to render this particular type
Expand Down
6 changes: 3 additions & 3 deletions fidget/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,16 +209,16 @@
//! ```
//! use fidget::{
//! context::{Tree, Context},
//! render::{BitRenderMode, ImageSize, RenderConfig},
//! render::{BitRenderMode, ImageSize, ImageRenderConfig},
//! vm::VmShape,
//! };
//!
//! let x = Tree::x();
//! let y = Tree::y();
//! let tree = (x.square() + y.square()).sqrt() - 1.0;
//! let cfg = RenderConfig::<2> {
//! let cfg = ImageRenderConfig {
//! image_size: ImageSize::from(32),
//! ..RenderConfig::default()
//! ..Default::default()
//! };
//! let shape = VmShape::from(tree);
//! let out = cfg.run::<_, BitRenderMode>(shape)?;
Expand Down
31 changes: 11 additions & 20 deletions fidget/src/mesh/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@
//! # Ok::<(), fidget::Error>(())
//! ```
use crate::render::Camera;

mod builder;
mod cell;
mod dc;
Expand All @@ -50,6 +48,8 @@ mod octree;
mod output;
mod qef;

use crate::render::{ThreadCount, View3};

#[cfg(not(target_arch = "wasm32"))]
mod mt;

Expand Down Expand Up @@ -83,37 +83,28 @@ pub struct Settings {
/// Depth to recurse in the octree
pub depth: u8,

/// Camera to provide a world-to-model transform
pub camera: Camera<3>,
/// Viewport to provide a world-to-model transform
pub view: View3,

/// Number of threads to use
///
/// 1 indicates to use the single-threaded evaluator; other values will
/// spin up _N_ threads to perform octree construction in parallel.
#[cfg(not(target_arch = "wasm32"))]
pub threads: std::num::NonZeroUsize,
pub threads: ThreadCount,
}

impl Default for Settings {
fn default() -> Self {
Self {
depth: 3,
camera: Default::default(),

#[cfg(not(target_arch = "wasm32"))]
threads: std::num::NonZeroUsize::new(8).unwrap(),
view: Default::default(),
threads: ThreadCount::default(),
}
}
}

impl Settings {
#[cfg(not(target_arch = "wasm32"))]
fn threads(&self) -> usize {
self.threads.get()
}

#[cfg(target_arch = "wasm32")]
fn threads(&self) -> usize {
1
}
/// Strong type for multithreaded settings
pub(crate) struct MultithreadedSettings {
pub depth: u8,
pub threads: std::num::NonZeroUsize,
}
7 changes: 5 additions & 2 deletions fidget/src/mesh/mt/dc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ use crate::mesh::{
types::{X, Y, Z},
Mesh, Octree,
};
use std::sync::atomic::{AtomicU64, Ordering};
use std::{
num::NonZeroUsize,
sync::atomic::{AtomicU64, Ordering},
};

#[derive(Debug)]
enum Task {
Expand Down Expand Up @@ -52,7 +55,7 @@ pub struct DcWorker<'a> {
}

impl<'a> DcWorker<'a> {
pub fn scheduler(octree: &Octree, threads: usize) -> Mesh {
pub fn scheduler(octree: &Octree, threads: NonZeroUsize) -> Mesh {
let queues = QueuePool::new(threads);

let map = octree
Expand Down
Loading

0 comments on commit 8c00f62

Please sign in to comment.