scenerygraphics / scenery

Flexible VR Visualisation for Volumetric and Geometric Data on the Java VM, powered by Kotlin and Vulkan.
https://scenery.graphics
GNU Lesser General Public License v3.0
131 stars 32 forks source link

Don't let volumes defeat push mode #684

Closed skalarproduktraum closed 9 months ago

skalarproduktraum commented 9 months ago

Simply using FloatArray.hashCode() caused the issue that UBO hashing in order to check for updates got defeated by new float arrays with the same contents being allocated. This happened because bigvolumeviewer copies float arrays behind the scenes when assigning them as a uniform. This PR replaces hashCode() calls on FloatArray and IntArray with contentHashCode(), which does not take the specific reference into account, but only the content of the array.

In addition, this PR also removes repeated allocations of the slicing equation array in Volume, and allocates the array only once.

xulman commented 9 months ago

isn't contentHashCode() more expensive than the plain hashCode()?

xulman commented 9 months ago

aha, but it's currently only 64 floats long... = 4 * MAX_SUPPORTED_SLICING_PLANES... that doesn't look too bad (I was worried that the float array holds the actual volumetric(!) image data...)

skalarproduktraum commented 9 months ago

It's quite well-defined how hashCode() behaves in Java for arrays (see the Javadoc in java.util.Arrays) - it'll only take into account referential equality. That however means you can change the content, but the reference stays the same, it's the same place in memory, after all.

I think using contentHashCode() here is the right way to go, as this is what Kotlin's standard library brings along for exactly this use case.

skalarproduktraum commented 9 months ago

Oh, and hashCode() itself is beyond our control. The one that does the deep comparison (to which contentHashCode() is a shortcut) lives in java.util.Arrays, while hashCode() itself is just the default one that uses referential equality.