Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Empty mesh for JitShape when translating box #47

Closed
julianschuler opened this issue Mar 24, 2024 · 2 comments · Fixed by #50
Closed

Empty mesh for JitShape when translating box #47

julianschuler opened this issue Mar 24, 2024 · 2 comments · Fixed by #50

Comments

@julianschuler
Copy link

Hi again,

I stumbled upon a case where meshing with a VmShape results in a correct mesh while meshing with a JitShape produces an empty one (on an x86 computer).

More specifically, this only seems to be the case when using a (mitered) box primitive and translating it along Z using remap_xyz(), but only for translations putting the box entirely above/below the XY-plane.

Here is a minimum working example reproducing this issue:

use fidget::{
    context::{IntoNode, Node},
    eval::MathShape,
    jit::JitShape,
    mesh::{Octree, Settings},
    vm::VmShape,
    Context, Error,
};

pub struct BoxShape {
    size: f64,
}

impl BoxShape {
    pub fn new(size: f64) -> Self {
        Self { size }
    }
}

impl IntoNode for BoxShape {
    fn into_node(self, context: &mut Context) -> Result<Node, Error> {
        let x = context.x();
        let y = context.y();
        let z = context.z();

        let abs_x = context.abs(x)?;
        let abs_y = context.abs(y)?;
        let abs_z = context.abs(z)?;

        let qx = context.sub(abs_x, self.size / 2.0)?;
        let qy = context.sub(abs_y, self.size / 2.0)?;
        let qz = context.sub(abs_z, self.size / 2.0)?;

        let max_elem = context.max(qx, qy)?;
        context.max(max_elem, qz)
    }
}

fn translate_z(
    context: &mut Context,
    root: impl IntoNode,
    translation: f64,
) -> Result<Node, Error> {
    let root = root.into_node(context)?;

    let x = context.x();
    let y = context.y();
    let z = context.z();
    let translated_z = context.sub(z, translation)?;

    context.remap_xyz(root, [x, y, translated_z])
}

fn main() -> Result<(), Error> {
    let settings = Settings {
        threads: 12,
        min_depth: 6,
        max_depth: 6,
    };

    for i in -5..=5 {
        let translation = i as f64 / 10.0;

        let mut context = Context::new();
        let box_shape = BoxShape::new(0.4);
        let root = translate_z(&mut context, box_shape, translation)?;

        let jit_shape = JitShape::new(&context, root)?;
        let jit_mesh = Octree::build(&jit_shape, settings).walk_dual(settings);
        let vm_shape = VmShape::new(&context, root)?;
        let vm_mesh = Octree::build(&vm_shape, settings).walk_dual(settings);

        println!(
            "translation: {:.1}  \t vertices (jit): {}\t vertices (vm): {}",
            translation,
            jit_mesh.vertices.len(),
            vm_mesh.vertices.len(),
        );
    }

    Ok(())
}

The output is the following (notice the lines with vertices jit: 0):

translation: -0.5  	 vertices (jit): 0	 vertices (vm): 14
translation: -0.4  	 vertices (jit): 0	 vertices (vm): 36
translation: -0.3  	 vertices (jit): 0	 vertices (vm): 21
translation: -0.2  	 vertices (jit): 14	 vertices (vm): 14
translation: -0.1  	 vertices (jit): 14	 vertices (vm): 14
translation: 0.0  	 vertices (jit): 14	 vertices (vm): 14
translation: 0.1  	 vertices (jit): 17	 vertices (vm): 17
translation: 0.2  	 vertices (jit): 14	 vertices (vm): 14
translation: 0.3  	 vertices (jit): 0	 vertices (vm): 21
translation: 0.4  	 vertices (jit): 0	 vertices (vm): 14
translation: 0.5  	 vertices (jit): 0	 vertices (vm): 42

Please let me know if I can help in any way resolving this.

@julianschuler julianschuler changed the title Meshing with JitShape has no vertices when translating box Empty mesh for JitShape when translating box Mar 24, 2024
@mkeeter
Copy link
Owner

mkeeter commented Mar 25, 2024

Interesting, thanks for the minimal example!

This looks like a bug in the x86 JIT specifically: running on AArch64, both JIT and VM evaluator give the same result.

It's not a bug in tape generation, because the system works with GenericVmShape::<12>::new(..) (i.e. building a VM-evaluated shape with only 12 registers, to match x86 JitShape).

(later)

I tracked it down to a bug in the x86 interval abs implementation, where we created a zero value by pulling from a high SIMD slot – which wasn't guaranteed to be empty!

Fixed by #50

mkeeter added a commit that referenced this issue Mar 25, 2024
Previously, we got a zero from a high value in the output XMM register,
which isn't actually guaranteed to be empty!

Fixes #47
@julianschuler
Copy link
Author

Thank you for the quick fix!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants