Closed osylum closed 1 year ago
Hi @osylum
Scene deallocation is currently a bit tricky with custom plugins. I believe that the bsdf
object is leaking between iteration loops. I'll skip the details here, this involves some pretty in-depth CPython/Pybind11/Mitsuba pieces.
First, let us comfirm that this is indeed the issue. Can you move the bsdf
loading outside of the loop so that it is only done once?
The rendering time stops increasing when moving these lines before the loop over light directions.
# define bsdf
# --------------------------------------------------------------------------
if bsdf_type == 'diffuse_custom':
bsdf = mi.load_dict({
'type': 'diffuse_custom',
'rho_d': [0.25012467, 0.04386179, 0.02270369],
})
elif bsdf_type == 'mitsuba': # test only
bsdf = mi.load_dict({
'type': 'plastic',
})
Is this good enough for you? Or is there some specific reason you need to define your plugins in the inner loops?
When looping over materials outside the loop over light directions, I have an increase each time I change material. It is less strong doing the loop in this manner, but when I have many materials it still result in a significant increase. I tried also to have a loop around the render_sphere() instead, to see if there would be some initialization at each call, but it did not change the result. Though, everytime I run the .py file it the rendering time starts from a fresh state. I tried reimporting mitsuba with importlib.reload and setting the variant at each call to render_sphere(), but it did not change the behavior as well. Is there a command to reset the state of mitsuba, as it would be at the start of running the .py file?
You could try using dr.registry_clear()
. This essentially flushes the just-in-time compiler that is used by mitsuba. Once you've called this function, you can no longer use any existing variables :warning:.
I tried using dr.registry_clear() inside the materials loop as follows:
dr.registry_clear() # can no longer used any existing variable
mi.set_variant('llvm_ad_rgb') # could not find LLVM-C.dll
# mi.set_variant('cuda_ad_rgb')
sensor = create_sensor()
object = create_object('sphere', bsdf_type, sphere_center, sphere_radius)
But at the second iteration, the program stopped with error at scene creation:
Process finished with exit code -1073740791 (0xC0000409)
The scene is:
scene = mi.load_dict({
'type': 'scene',
'integrator': {
'type': 'direct', # no need for indirect lighting
'emitter_samples': emitter_samples,
'hide_emitters': True
},
'emitter':emitter,
'object': object,
'sensor': sensor
})
with components:
emitter:
PointLight[
position = [0, -3, 0],
intensity = UniformSpectrum[value=[2]],
medium = none]
object:
Sphere[
to_world = [[0.5, 0, 0, 0],
[0, 0.5, 0, 0],
[0, 0, 0.5, 0],
[0, 0, 0, 1]],
center = [0, 0, 0],
radius = 0.5,
surface_area = [3.14159],
bsdf = CookTorrance[
rho_d=[[0.03126385062932968, 0.01777799427509308, 0.014777406118810177]],
rho_s=[[0.15480387210845947, 0.14453330636024475, 0.15086358785629272]],
eta=1.25005616,
roughness=0.12849635,
]
]
sensor:
PerspectiveCamera[
x_fov = [38.8839],
near_clip = 0.01,
far_clip = 10000,
film = HDRFilm[
size = [864, 486],
crop_size = [864, 486],
crop_offset = [0, 0],
sample_border = 0,
filter = LanczosSincFilter[lobes=3.000000],
file_format = OpenEXR,
pixel_format = rgba,
component_format = float16,
],
sampler = IndependentSampler[
base_seed = 0
sample_count = 4
samples_per_wavefront = 1
wavefront_size = 0
],
resolution = [864, 486],
shutter_open = 0,
shutter_open_time = 0,
to_world = [[-1, 0, 0, 0],
[0, -0, 1, -3],
[0, 1, 0, 0],
[0, 0, 0, 1]]
]
Setting or not the variant does not change the behavior. Question: Is there something I might be doing wrong?
As mentioned previously, I had tried to update the object bsdf, in place of making a new call to load_dict. I used:
object_params = mi.traverse(object)
but the properties that I see are only:
object_params SceneParameters[
---------------------------------------------------------------
Name Flags Type Parent
---------------------------------------------------------------
to_world ∂, D Transform4f Sphere
Question: Is it a good approach? If so, how can I set the bsdf with this approach?
Yes this all seems reasonable. The BSDF
type cannot be changed by using traverse()
you need to, as you already are doing, create a new BSDF and insert it into a new scene.
Another suggestion would be to rewrite your code such that render_sphere takes a single BSDF and Emitter type, and do all the necessary mitsuba imports in that function. With this you can launch a new process that executes this function for every configuration you want to generate.
Hi @osylum @njroussel , I am still confused with this cosine foreshortening part: diffuse.cpp multiplies the brdf by cos_theta_o. It is probably right, but it is not clear to me why it is not multiplied by cos_theta_i instead (<normal,light>). I still have to learn more about importance sampling, so maybe there is something I don't understand when you talk about cosine foreshortening factor - that I understand to be the shadowing term in the render equation. Did you understand this?
Hello @colinzhenli,
Your question is unrelated to this issue, please open a new Discussion with your question if needed.
Summary
Rendering time increases with consecutive renders using custom shader.
System configuration
System information:
OS: Windows-10 CPU: Intel64 Family 6 Model 165 Stepping 5, GenuineIntel GPU: NVIDIA RTX A4000 Python: 3.9.7 (tags/v3.9.7:1016ef3, Aug 30 2021, 20:19:38) [MSC v.1929 64 bit (AMD64)] NVidia driver: 517.40 CUDA: 10.0.130 LLVM: 15.-1.-1
Dr.Jit: 0.4.0 Mitsuba: 3.2.0 Is custom build? False Compiled with: MSVC 19.34.31937.0 Variants: scalar_rgb scalar_spectral cuda_ad_rgb llvm_ad_rgb
Description
I have a very simple scene with a sphere, a point light and a bsdf material (custom or mitsuba one). I loop over light directions and create a new point light emitter, sphere with bsdf (in the original code I have also a loop over bsdf materials) and scene at each iteration. When using a mitsuba bsdf (e.g. diffuse), the render time remain pretty much constant. But when I use a custom bsdf (dummy diffuse in python), the render time keeps increasing. Could please help me to understand and improve the behavior?
I have also side questions in terms of rendering time:
Side notes:
Thank you
Steps to reproduce
Here is a minimal example. You change the bsdf_type in the main function. Behavior is similar when using llvm_ad_rgb versus cuda_ad_rgb variants.