MRtrix3 / mrtrix3

MRtrix3 provides a set of tools to perform various advanced diffusion MRI analyses, including constrained spherical deconvolution (CSD), probabilistic tractography, track-density imaging, and apparent fibre density
http://www.mrtrix.org
Mozilla Public License 2.0
295 stars 182 forks source link

MRView: Lazy loading of 3d textures #234

Closed rtabbara closed 9 years ago

rtabbara commented 9 years ago

Currently, loading of 3d textures onto the GPU for images with a relatively high resolution can be quite an expensive operation, which in some instances can cause MRView to hang for a bit.

I was wondering whether it was worth allowing these 3d textures to be loaded incrementally per draw call rather than all at once. To add support for the progress bar, Image::copy_texture_3D is already designed in a way that partitions the uploading of the texture data, so enabling lazy loading wouldn't be too drastic a change.

I also thought it might be cool in the Volume mode to see the image built up as you loaded the 3d texture for the first time.

draffelt commented 9 years ago

A whole brain 3D progress bar...I like it.

jdtournier commented 9 years ago

A whole brain 3D progress bar...I like it.

:neckbeard:

I've also thought about incremental updates (although in quite a different way from this) but never really convinced myself that it could be done seamlessly. The problem as I see it is that the overwhelming majority of the time, you'll be loading the 3D texture for a generic tilted slice view. Having an incremental update might feel really weird in this case - and might actually jar even more. For example, if you happen to be displaying an axial slice, and just tilt the viewing plane slightly, that will trigger the upload of the 3D texture. If you do it incrementally, there will be no screen update until the data for that slice starts to come in, which may be halfway through or worse - during that time, there will be no visual feedback about this at all.

Also, while it would be fun to watch the 3D volume fill up, remember that a 3D volume render will generally be an expensive operation, especially for less-than-great hardware. So you might find that the load time grows massively in that case due to large number of renders during the load.

This issue isn't actually limited to the volume render either. You might be displaying render-intensive stuff (e.g. OFD overlay, lots of streamlines - especially with geometry shader now merged :wink: ), so again, load times might grow massively if the time taken per render is larger than the time to load a slice of data...

What should be happening when load times exceed half a second (I think) is that a progressbar will pop up to provide visual feedback as to what is going on. If that's not working, I'd rather we fixed that...

rtabbara commented 9 years ago
For example, if you happen to be displaying an axial slice, and just tilt the viewing plane slightly, that will trigger the upload of the 3D texture.

Yep, right now the 3d texture is incrementally built up along the z-axis, so what we could do is build the texture around a neighbourhood of the current focus (i.e. 0, +1, -1, +2, -2, etc. increment of the current V[2] voxel value). That way in the case of an axial slice you would immediately get visual feedback when moving from a 2d to 3d texture.

For the cases of sagital/coronal slices, if we wanted to be even fancier we could adjust the axis used to load the texture accordingly, so that again the entire texture would immediately be viewable.

Another benefit that might sway you is that this would be a nice way to handle volume changes when using a 3d texture --- in particular I noticed that when using the screen capture tool to animate volume changes, each frame would have to reload the entire 3d texture making the previewing a pretty choppy experience. In the lazy approach, you would only load the slice frame you're interested in (probably also need (edit) +n,-n for interpolation).

Also, while it would be fun to watch the 3D volume fill up, remember that a 3D volume render will generally be an expensive operation, especially for less-than-great hardware. So you might find that the load time grows massively in that case due to large number of renders during the load.

Well, if we incorporate the above suggestion of loading from the current focus, then the issue of waiting for visual feedback when viewing slices goes away. In the case of a volume, you're seeing everything anyway so you're going to always see part of the texture. Also, I'm not too sure that uploading a single slice per draw call is going to be a huge added burden on the pipeline. In the case of a pure 2d texture, when traversing slices we're constantly recreating the texture and that doesn't seem to cause any noticeable slowdown even when overlaying our rendering with other tools.

If I haven't wooed you then that's fine. But when grant season comes around and you need a cool visualisation of a rotating brain that builds up before your eyes, think about what you missed out on.

jdtournier commented 9 years ago

Well, it's not that I don't think it would be fun, but I don't see how you could implement that in a way that doesn't slow things down dramatically, particularly for the worst-case scenarios (expensive frame updates). And I also don't see that it would be trivial to implement lazy loading in a way that preferentially loads the slice displayed without massive overhead to support the worst-case scenario there (strongly oblique slices). I also see this might cause issues for the screen capture unless handled properly and very differently for that case. To expand:

So all in all, I think this would actually create many more problems than it solves... It's really not trivial to get right. Maybe others have opinions on the matter...?

rtabbara commented 9 years ago

@jdtournier Fair enough. I agree that it could get messy pretty quickly and for all the work to get it right, it's probably not worth the reward. Might consider revisiting this, but for now I'll close this off.