mitsuba-renderer / drjit

Dr.Jit — A Just-In-Time-Compiler for Differentiable Rendering
BSD 3-Clause "New" or "Revised" License
601 stars 45 forks source link

Fix dynamic dispatch calls which are fully masked #221

Closed njroussel closed 8 months ago

njroussel commented 8 months ago

This PR fixes evaluted dynamic dispatches which are fully masked.

The return value (if there is one) of an evaluated dynamic dispatch which is fully masked is completely arbitrary in theory: it should never be used. In practice, JIT internals expect the return value to be properly initialized to something. The previous code would not initialize the return value, and would hence crash the user's script. This might seen like a corner case, but in reality it is extremely frequent when rendering in wavefront-mode with Mitsuba 3.

In this PR, the return value is zero-initialized, such that it is consistent with a symbolic dispatch. Python dr.dispatch statements make use of https://github.com/mitsuba-renderer/drjit-core/pull/86 to trace an arbitrary instance. This is necessary to figure out the return value type. Special care needs to be taken when calling a fully-masked target, even though it's return value won't be used it might still generate side-effects. Tests were added to check the new behavior.

wjakob commented 8 months ago

Am I understanding correctly that this fix is specific to Python? (The call to _peek occurs in the Python bindings). Does the issue not arise on the C++ side? Other than that, the changes look good to me.

njroussel commented 8 months ago

Not quite, it's a cascade of two things:

(Technically, we could use the registry_peek function in C++ too - at the cost of tracing a function rather than immediately returning zeros when self is set to nullptr. )

wjakob commented 8 months ago

Great. Returning zeros based on the known type is the way to go whenever possible.