Page MenuHome

Cycles: Fix possible use of uninitialized ShaderClosure
ClosedPublic

Authored by Sergey Sharybin (sergey) on May 11 2021, 4:35 PM.

Details

Summary

It is possible that BSDF allocation will advance pointer in the
allocation "pool" but will return null pointer if the weight is
too small.

One artist-measurable issue this change fixes is random issues
with denoising: normal pass for denoising could have accessed
non-initialized normal of a closure.

Diff Detail

Repository
rB Blender
Branch
cycles_closure_alloc (branched from master)
Build Status
Buildable 14514
Build 14514: arc lint + arc unit

Event Timeline

Sergey Sharybin (sergey) requested review of this revision.May 11 2021, 4:35 PM
Sergey Sharybin (sergey) created this revision.

By "de-allocate" I've meant something like this P2114.

It shouldn't be a performance penalty as under normal circumstances this code is never run.
From quick looking around it also seems that the usages where we loop over closures will be fine:

  • Some of the loops are summing wrights, and adding very small value shouldn't make it a difference
  • Some checks will ignore the closure (since the type is CLOSURE_NONE_ID)
  • Some checks will indirectly try to consider the BSDF, but will do early output in a deeper calls (i.e. the BSDF blurring).

However, not sure why we were leaving such non-fully-initialized closures around. If there is a good reason to keep them around, would be good to have a comment about it. If there is no good reason, do we remove them AND tweak type check? Or do we only remove those closures?

I think moving the sample weight check earlier in the bsdf_alloc and bsdf_alloc_osl functions might be better, unless there is some issue with that.

Not sure if avoiding that > check is over-optimizing things, probably it does not make a measurable difference. But it's rather pointless to store a CLOSURE_NONE_ID.

Use early output check in bsdf_alloc()

Indeed seems better approach than storing CLOSURE_NONE_ID.
Initially, missed that it's possible to ignore those with a simple
early output though :)

This revision is now accepted and ready to land.May 11 2021, 6:12 PM

Fixes while chasing regression suit failure of the previous
version of this patch.

Use more NaN/inf safe way to check sample weight. It is not
fully robust, hence I did not add comment about it. For now
what is the most important is avoid functional changes for
the regular files. So from this point of view used the same
way of comparison as it used to be.

Ideally would add an assert in the BSDF allocation to catch
cases when non-finite weight is passed to catch actual root
causes.

The failing test was tangent_missing_uv.blend. I'll give it
a deeper dig outside of this patch to track where non-finite
BSDF weight is coming from.

Additionally, fixed possible access to the first closure if
the shader has no closures. This is a bit annoying, but seems
to be right thing to do, and, hopefully, will not show up in
a profiler.

Sergey Sharybin (sergey) requested review of this revision.May 11 2021, 8:18 PM
Sergey Sharybin (sergey) retitled this revision from Cycles X: Fix possible use of uninitialized ShaderClosure to Cycles: Fix possible use of uninitialized ShaderClosure.May 11 2021, 8:34 PM

Added a brief comment about using the if the way we use it
(so that people pay a bit more attention when/if converting
to an early output).

Brecht Van Lommel (brecht) added inline comments.
intern/cycles/kernel/kernel_shader.h
639

This should not be necessary. If it was I think we'd already be having issues when using e.g. just an emission shader or none at all.

689

Same.

This revision is now accepted and ready to land.May 11 2021, 9:10 PM

Removed changes in the phase sampling and BSDF picking.

BSDF picking is only used when shader data is tagged with presense of
BSDF, so it must have at least one BSDF. So the check was redundant.

The volume is a bit more tricky to me to fully follow, but also seems
that it is only used from place where we know we have volume.

In any case, lets play it safe and commit allocation changes which
we know work and solve actual problem. The rest we can re-iterate
separately.

I'll commit the allocation fix to 2.93, This is what I understood you
prefer as well :)