Skip to content

Uniform buffers for shader props, allow variable number of channels, update deck.gl to 9.2.9#924

Open
xinaesthete wants to merge 77 commits intohms-dbmi:mainfrom
xinaesthete:deck_9.2
Open

Uniform buffers for shader props, allow variable number of channels, update deck.gl to 9.2.9#924
xinaesthete wants to merge 77 commits intohms-dbmi:mainfrom
xinaesthete:deck_9.2

Conversation

@xinaesthete
Copy link
Copy Markdown
Contributor

@xinaesthete xinaesthete commented Nov 8, 2025

Fixes #687

Background

#687 as well as elsewhere for discussion of UBO etc.

This is work-in-progress... started out just trying to update to latest luma.gl/deck.gl to deal with some peer-dependency issues downstream. Latest versions remove the deprecated setUniforms etc, so this is becoming more pressing.

This is still WIP as of this writing, but I think starting to take shape for a way of supporting N-channels without too much pain for extension authors.

Change List

  • declaring shader uniforms as UBO
  • setting props with model.shaderInputs rather than setUniforms
  • tending to prefer implementing updateState() rather than draw(), I think this is more in line with how things are supposed to be
  • trying to make sure any assumptions about MAX_CHANNELS = 6 is findable in the code etc...
  • shaders have a define for NUM_CHANNELS which should be used consistently where relevant
  • initial version of a shader code preprocessor wrapped in a new VivShaderAssembler class for expanding lines with <VIV_CHANNEL_INDEX>...

Checklist

  • Update JSdoc types if there is any API change.
  • Make sure Avivator works as expected with your change.
  • Update documentation for migrating shader extensions to the new form once the design is settled.

@xinaesthete xinaesthete changed the title Deck 9.2 Uniform buffers for shader props, allow variable number of channels Nov 8, 2025
@dbmi-svc-checkmarx
Copy link
Copy Markdown

dbmi-svc-checkmarx commented Nov 8, 2025

Logo
Checkmarx One – Scan Summary & Details530f1bc2-c855-4937-8261-34d77ee495ea


New Issues (3) Checkmarx found the following issues in this Pull Request
# Severity Issue Source File / Package Checkmarx Insight
1 LOW Unpinned Actions Full Length Commit SHA /ci.yml: 39
detailsPinning an action to a full length commit SHA is currently the only way to use an action as an immutable release. Pinning to a particular SHA help...
2 LOW Unpinned Actions Full Length Commit SHA /ci.yml: 32
detailsPinning an action to a full length commit SHA is currently the only way to use an action as an immutable release. Pinning to a particular SHA help...
3 LOW Unpinned Actions Full Length Commit SHA /release.yml: 34
detailsPinning an action to a full length commit SHA is currently the only way to use an action as an immutable release. Pinning to a particular SHA help...

Fixed Issues (3) Great job! The following issues were fixed in this Pull Request
Severity Issue Source File / Package
LOW Unpinned Actions Full Length Commit SHA /release.yml: 33
LOW Unpinned Actions Full Length Commit SHA /ci.yml: 37
LOW Unpinned Actions Full Length Commit SHA /ci.yml: 30

Use @Checkmarx to interact with Checkmarx PR Assistant.
Examples:
@Checkmarx how are you able to help me?
@Checkmarx rescan this PR

Copy link
Copy Markdown
Collaborator

@ilan-gold ilan-gold left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's reasonable to ask in deck.gl slack or on the github what the implications of a custom ShaderAssembler would be. I really couldn't know off hand. As you can probably tell, I did a lot of this by just looking at the underlying code and ballparking what would be needed. The upside is it works. The downside is that it has a bunch of private accesses. At the time, I was under paper pressure :/

I don't feel too strongly about how off-the-beaten-path this goes as long as it works. We advertise breaking changes on the minor version so I'm also not worried about any breaking changes. I'll try to download the deck.gl slack on Monday again.


const _RENDER = `\
float intensityArray[6] = float[6](intensityValue0, intensityValue1, intensityValue2, intensityValue3, intensityValue4, intensityValue5);
float intensityArray[NUM_CHANNELS] = float[NUM_CHANNELS](intensityValue0, intensityValue1, intensityValue2, intensityValue3, intensityValue4, intensityValue5);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is great!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that there is one other place where I have something more like

float array[NUM_CHANNELS] = float[NUM_CHANNELS](
  value<VIV_CHANNEL_INDEX>,
);

and that also works...

Now I'm trying to get that to also work for uniform vec2 constastLimits<VIV_CHANNEL_INDEX>; with the new shaderInputs UBO binding and finding it tricky.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or rather... the syntax I mentioned works ok, but the new

uniform xrLayerUniforms {
  vec2 contrastLimits<VIV_CHANNEL_INDEX>;
} xrLayer;

I'm struggling with.

Copy link
Copy Markdown
Contributor Author

@xinaesthete xinaesthete Nov 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the issue may be that I was trying to implement setting shaderInputs in the draw() method and moving this to updateState() makes a significant difference (just about to try this). edit: also, working in js rather than ts and having typos.

Comment on lines +80 to +81
// does any of this existing logic need to change?
// (like, is there ever more than one model?)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the way our extensions are structured, no, because extension is attached to XRLayer which does its own rendering?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I don't anticipate a problem there... In some places I'm looping over this.getModels() and it may be that it would be somewhat safer to do that a bit more consistently, but I'm pretty sure it isn't likely to matter in foreseeable future. Slight balance between consistency and avoiding changes where there isn't a solid reason for it.

@xinaesthete
Copy link
Copy Markdown
Contributor Author

@ilan-gold Ib already expressed some enthusiasm about viv updating deck versions and I'm sure he'll be happy to give some more feedback at some point. I'll add a pointer to this PR over there now.

@xinaesthete
Copy link
Copy Markdown
Contributor Author

n.b. I've made all the CI pass and will try to keep commits clean WRT that, but bear in mind that I don't think the configuration is properly working for '@deck.gl/test-utils' as noted #921 so we need to be extra careful to manually verify that layers/extensions etc do actually work correctly.

@xinaesthete
Copy link
Copy Markdown
Contributor Author

Also I think that volume minimum intensity projection is already buggy - it looks similar in this branch to production avivator build, which is to say, not good.

@ilan-gold
Copy link
Copy Markdown
Collaborator

Also I think that volume minimum intensity projection is already buggy - it looks similar in this branch to production avivator build, which is to say, not good.

Yes it is, should eventually fix that...

@keller-mark
Copy link
Copy Markdown
Member

I am not sure that minimum intensity projection has bugs, it is just that it is not really useful, conceptually, for most images. I think it was implemented because it is very easy once you implement the max-intensity projection. But why would I want to view the "minimum-intensity" pixels, when they are just going to correspond the black space that I am not typically interested in?

I think the only time it would really make sense is if the image colors have been inverted for some reason.

(Maybe I am wrong, but before we assume it has bugs we should verify with another viewer that supports MinIP)

@ilan-gold
Copy link
Copy Markdown
Collaborator

You're right @keller-mark I was mostly speaking from an experience where I wanted the inversion actually and remember it not working properly. But I don't know for sure.

@xinaesthete xinaesthete marked this pull request as ready for review March 5, 2026 15:00
@xinaesthete
Copy link
Copy Markdown
Contributor Author

Documentation probably still needs some work.

@xinaesthete xinaesthete marked this pull request as draft March 6, 2026 17:05
@xinaesthete xinaesthete mentioned this pull request Mar 9, 2026
@xinaesthete xinaesthete marked this pull request as ready for review March 9, 2026 13:46
@xinaesthete
Copy link
Copy Markdown
Contributor Author

There seems to be a fairly major performance degradation with volume rendering currently – I would expect it to be faster than before as long as it's rendering a lower number of channels, and I believe this was the case previously, so I'll try to figure out what's going on there.

@xinaesthete
Copy link
Copy Markdown
Contributor Author

xinaesthete commented Mar 10, 2026

There seems to be a fairly major performance degradation with volume rendering currently – I would expect it to be faster than before as long as it's rendering a lower number of channels, and I believe this was the case previously, so I'll try to figure out what's going on there.

edit: I have noticed that it seems much worse for camera interactions than tweaking contrast-limits. At least with my local changes there are intermittent pauses when moving the camera, so this is something to investigate; seems like the shader details are not so relevant. I might post on the deck.gl Slack.

Also, I think I've been seeing some stutters in 2D as well, but not on the same level.

older comments

I've realised I've got channel-expansion to arrays inside the hot-path of the raymarch loop in the volume shader... whoops... that'd likely explain some performance degradation. I think this is actually all pretty trivial these days and I'm not seeing much change from hoisting things out of loops etc; I expect somewhere up the GLSL compiler stack it's able to do that automatically.

It seems that there are calls being made to bufferSubData every frame which surely shouldn't be necessary. Wasn't thinking straight there – this is the normal expected UBO updating, I don't think I've seen texture data being thrashed.

Hopefully it's just a case of tweaking updateState / draw etc.

@ilan-gold
Copy link
Copy Markdown
Collaborator

ilan-gold commented Mar 19, 2026

@xinaesthete Apologies, was probably https://github.com/xinaesthete/viv/blob/deck_9.2/packages/viewers/src/VivViewer.jsx#L73-L75 which doesn't actually seem to work on everyone's machines/site builds.

I reverted it in #948 but am waiting on @keller-mark there. Maybe I should just revert globally. Sorry for the trouble!

commit 91560ab
Author: Ilan Gold <ilanbassgold@gmail.com>
Date:   Thu Mar 19 17:22:12 2026 +0100

    fix: remove debounce (hms-dbmi#952)
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9.5.0
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed these because at one point I didn't realise that CI on the branch was running on an automatic merge with main and I was trying to figure out why CI was failing when everything worked locally. package.json has "packageManager": "pnpm@9.5.0", there may be something to be said for making sure that these are all tied to the same version, but the change isn't necessary to the PR (CI was breaking because of silently auto-merged pnpm-lock.yml I think), and if we make a separate change it'd probably also update to a newer version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Max channels allowed

4 participants