mitsuba-renderer / mitsuba3

Mitsuba 3: A Retargetable Forward and Inverse Renderer
https://www.mitsuba-renderer.org/
Other
2.1k stars 250 forks source link

Segmentation fault in `put_block` when trying to use an integrator directly. #401

Open expenses opened 2 years ago

expenses commented 2 years ago

Summary

I tried to follow https://mitsuba.readthedocs.io/en/stable/src/rendering/scripting_renderer.html but modify it so that the scene integrator is used instead:

import mitsuba as mi
import drjit as dr

mi.set_variant('llvm_ad_rgb')

scene = mi.load_file('scenes/cbox.xml')

# Camera origin in world space
cam_origin = mi.Point3f(0, 1, 3)

# Camera view direction in world space
cam_dir = dr.normalize(mi.Vector3f(0, -0.5, -1))

# Camera width and height in world space
cam_width  = 2.0
cam_height = 2.0

# Image pixel resolution
image_res = [256, 256]

# Construct a grid of 2D coordinates
x, y = dr.meshgrid(
    dr.linspace(mi.Float, -cam_width  / 2,   cam_width / 2, image_res[0]),
    dr.linspace(mi.Float, -cam_height / 2,  cam_height / 2, image_res[1])
)

# Ray origin in local coordinates
ray_origin_local = mi.Vector3f(x, y, 0)

# Ray origin in world coordinates
ray_origin = mi.Frame3f(cam_dir).to_world(ray_origin_local) + cam_origin

ray = mi.Ray3f(o=ray_origin, d=cam_dir)

sensor = scene.sensors()[0]
film = sensor.film()

(spec, mask, aov) = scene.integrator().sample(scene, sensor.sampler(), ray, medium=None, active=True)
image_block = mi.ImageBlock([256, 256], [0, 0], 3)
image_block.put(mi.Vector2f(x, y), spec)
film.put_block(image_block)

image = film.develop()

mi.util.write_bitmap("my_first_render.png", image)

This resulted in a segmentation fault. Backtrace from gdb:

Thread 1 "python" received signal SIGSEGV, Segmentation fault.
0x00007ffff4b75dde in mitsuba::ImageBlock<drjit::DiffArray<drjit::LLVMArray<float> >, mitsuba::Color<drjit::DiffArray<drjit::LLVMArray<float> >, 3ul> >::put_block(mitsuba::ImageBlock<drjit::DiffArray<drjit::LLVMArray<float> >, mitsuba::Color<drjit::DiffArray<drjit::LLVMArray<float> >, 3ul> > const*) () from /home/ashley/projects/mitsuba-baking/env/lib/python3.10/site-packages/mitsuba/libmitsuba.so
(gdb) bt
#0  0x00007ffff4b75dde in mitsuba::ImageBlock<drjit::DiffArray<drjit::LLVMArray<float> >, mitsuba::Color<drjit::DiffArray<drjit::LLVMArray<float> >, 3ul> >::put_block(mitsuba::ImageBlock<drjit::DiffArray<drjit::LLVMArray<float> >, mitsuba::Color<drjit::DiffArray<drjit::LLVMArray<float> >, 3ul> > const*) ()
   from /home/ashley/projects/mitsuba-baking/env/lib/python3.10/site-packages/mitsuba/libmitsuba.so
#1  0x00007fffe6f0f8c8 in mitsuba::HDRFilm<drjit::DiffArray<drjit::LLVMArray<float> >, mitsuba::Color<drjit::DiffArray<drjit::LLVMArray<float> >, 3ul> >::put_block(mitsuba::ImageBlock<drjit::DiffArray<drjit::LLVMArray<float> >, mitsuba::Color<drjit::DiffArray<drjit::LLVMArray<float> >, 3ul> > const*) ()
   from /home/ashley/projects/mitsuba-baking/env/lib/python3.10/site-packages/mitsuba/plugins/hdrfilm.so
#2  0x00007fffd1c9d20e in ?? ()
   from /home/ashley/projects/mitsuba-baking/env/lib/python3.10/site-packages/mitsuba/mitsuba_llvm_ad_rgb_ext.cpython-310-x86_64-linux-gnu.so
#3  0x00007fffd1a96523 in ?? ()
   from /home/ashley/projects/mitsuba-baking/env/lib/python3.10/site-packages/mitsuba/mitsuba_llvm_ad_rgb_ext.cpython-310-x86_64-linux-gnu.so
#4  0x00007ffff7b554a1 in ?? () from /usr/lib/libpython3.10.so.1.0
#5  0x00007ffff7b4eb4b in _PyObject_MakeTpCall ()
   from /usr/lib/libpython3.10.so.1.0
#6  0x00007ffff7b60e06 in ?? () from /usr/lib/libpython3.10.so.1.0
#7  0x00007ffff7b49687 in _PyEval_EvalFrameDefault ()
   from /usr/lib/libpython3.10.so.1.0
#8  0x00007ffff7b43760 in ?? () from /usr/lib/libpython3.10.so.1.0
--Type <RET> for more, q to quit, c to continue without paging--
#9  0x00007ffff7bf0e04 in PyEval_EvalCode () from /usr/lib/libpython3.10.so.1.0
#10 0x00007ffff7c015b3 in ?? () from /usr/lib/libpython3.10.so.1.0
#11 0x00007ffff7bfcd0a in ?? () from /usr/lib/libpython3.10.so.1.0
#12 0x00007ffff7aa11cd in ?? () from /usr/lib/libpython3.10.so.1.0
#13 0x00007ffff7aa0e7e in _PyRun_SimpleFileObject () from /usr/lib/libpython3.10.so.1.0
#14 0x00007ffff7aa1831 in _PyRun_AnyFileObject () from /usr/lib/libpython3.10.so.1.0
#15 0x00007ffff7c0dd9d in Py_RunMain () from /usr/lib/libpython3.10.so.1.0
#16 0x00007ffff7be25eb in Py_BytesMain () from /usr/lib/libpython3.10.so.1.0
#17 0x00007ffff783c290 in ?? () from /usr/lib/libc.so.6
#18 0x00007ffff783c34a in __libc_start_main () from /usr/lib/libc.so.6
#19 0x0000555555555045 in _start ()

Note that I'm not using image_block = film.create_block() here. This is because the image block that is created has a channel_count of 0 for some reason.

I'm probably doing something very wrong in my own code here, but there are unfortunately not any tutorials for using Integration.sample. See https://github.com/mitsuba-renderer/mitsuba3/discussions/395.

System configuration

System information:

OS: Arch Linux 6.0.9-arch1-1 CPU: 11th Gen Intel i7-1165G7 GPU: Intel TigerLake-LP GT2 [Iris Xe Graphics] Python version: Python 3.10.8 LLVM version: 14.0.6 CUDA version: N/A NVidia driver: N/A

Dr.Jit version: 0.2.2 (?) Mitsuba version: Mitsuba version 3.0.2 (master[f2d2f1f], Linux, 64bit, 8 threads, 8-wide SIMD) Enabled processor features: cuda llvm avx f16c sse4.2 x86_64

  1. Run the above script
njroussel commented 2 years ago

Hi @expenses

You were almost there, there are just a few steps missing: 1) You need to further initialize the film by calling film.prepare([]). With this, it knows how many channels it is supposed to hold. 2) You couldn't use film.create_block() because of the previous point, you should use this rather than building one yourself. 3) The sampler also needs a few more steps to be fully initialized. First we need to specify its "depth" sensor.sampler().set_samples_per_wavefront(1) and then we also need to properly seed it sampler.seed(0xDEADCAFE, image_res[0] * image_res[1]) 4) The image block has a weight per sample, so when you should be doing something like this image_block.put(mi.Vector2f(x, y), [spec.x, spec.y, spec.z, 1]).

With these changes, I've managed to run your any crashes. However, the output is all black, I think something in your camera or ray direction might be flawed. I'll let you look into that.

Doing something as simple as you are here is definitely more awkward than we'd like. We'll figure out a simpler solution, or at least improve the documentation to make this easier to reproduce.

expenses commented 2 years ago

@njroussel wonderful, thanks!

expenses commented 2 years ago

Yep, that works! I just needed to also change how the output is written:

diff --git a/old.py b/new.py
index 27fafb4..3c36979 100644
--- a/old.py
+++ b/x.py
@@ -24,6 +24,11 @@ x, y = dr.meshgrid(
     dr.linspace(mi.Float, -cam_height / 2,  cam_height / 2, image_res[1])
 )

+dest_x, dest_y = dr.meshgrid(
+    dr.arange(dr.llvm.Float, image_res[0]),
+    dr.arange(dr.llvm.Float, image_res[1])
+)
+
 # Ray origin in local coordinates
 ray_origin_local = mi.Vector3f(x, y, 0)

@@ -34,10 +39,13 @@ ray = mi.Ray3f(o=ray_origin, d=cam_dir)

 sensor = scene.sensors()[0]
 film = sensor.film()
+film.prepare([])
+sampler = sensor.sampler()
+sampler.seed(0xDEADCAFE, image_res[0] * image_res[1])

-(spec, mask, aov) = scene.integrator().sample(scene, sensor.sampler(), ray, medium=None, active=True)
-image_block = mi.ImageBlock([256, 256], [0, 0], 3)
-image_block.put(mi.Vector2f(x, y), spec)
+(spec, mask, aov) = scene.integrator().sample(scene, sampler, ray, medium=None, active=True)
+image_block = film.create_block()
+image_block.put((dest_x, dest_y), [spec.x, spec.y, spec.z, 1.0])
 film.put_block(image_block)

 image = film.develop()

Output: my_first_render

expenses commented 2 years ago

I'm going to keep this open for a bit because the SEGFAULT still seems bad. I might see if I can debug it later.