feat(segmentation_user_layer): add user shader for segmentation layers with support for segment properties - #1074
Conversation
07f7c7c to
7adf3fc
Compare
7adf3fc to
53cfe9b
Compare
seankmartin
left a comment
There was a problem hiding this comment.
This looks nice, thanks for all the changes! In general the API in the shader seems pretty reasonable to me. I've not gotten to go through it all, but some small comments from what I have looked through. There are also some TODO markers and the likes, not sure if those are still relevant or you settled on the approach in those cases
| colorGroupState.segmentColorHash.compute(color, objectId); | ||
| return color; | ||
| const { getShaderSegmentColor } = displayState; | ||
| return getShaderSegmentColor(objectId) ?? color; |
There was a problem hiding this comment.
Could we detect if the shader is the default one, and in that case use the old non-shader color path to display the colors in the UI for performance. I noticed that the segmentation menu can sometimes feel a bit more sluggish to go through, which seems pretty fair when you've chosen to use the segment shader and to me it seems fine. But if possible to avoid this slight hit if you didn't change your shader I think that would be good
There was a problem hiding this comment.
I think that is what I should do for now but maybe I should give a quick try at adding batching. I don't notice sluggishness but I do notice that the color doesn't load immediately if scrolling very fast on my machine. I can't replicate that on the main branch.
It's easy to add support to calculate many segment colors in a single draw call, the issue is that the segment list is designed so that each row is processed independently. But if I can get it working, it should be far more performant.
There was a problem hiding this comment.
That makes a lot of sense, thanks Chris
There was a problem hiding this comment.
@seankmartin can you check if this deployment has noticeably better performance for you?
There was a problem hiding this comment.
Oh wow, that's so much better yes thanks @chrisj
| const hasStringProperty = inlineProperties.properties.some( | ||
| (p) => p.type === "string", | ||
| ); | ||
| if (!hasStringProperty) { |
There was a problem hiding this comment.
I guess this is leftover but it does raise what we should do here. Shader error comes to mind, but then in theory the underlying data could change and lose a property. Maybe that's fine though.
There was a problem hiding this comment.
yeah that was for demonstration as string properties are not common. But do you mean if a shader references a property that was later removed from the segment properties file? If so I think the current error "property does not exist" is correct.
| }); | ||
| } | ||
|
|
||
| function makeSkeletonShaderCodeWidget(layer: SegmentationUserLayer) { |
| } | ||
|
|
||
| export const DEFAULT_FRAGMENT_SEGMENT_COLOR = ` | ||
| vec3 segmentColor(vec3 color, bool hasProperties, bool isStated) { |
There was a problem hiding this comment.
Oh also minor but leading newline in the resulting shader here that probably is better left out
There was a problem hiding this comment.
also I should rename it from FRAGMENT becomes it is sometimes used in the vertex shader
|
@seankmartin thanks for the review! I have some changes I'll push shortly that I noticed yesterday |
sounds great, thanks! |
00444f6 to
9f4e76c
Compare
72bcce9 to
b3fd516
Compare
|
@seankmartin I simplified the performance optimizations and added it to this PR. I added a temporary setting that you can toggle with "q" to easily observe the difference. Can you give it a test to see if you are still see the big performance improvement? I can see the a difference when I press "q" on and off while dragging the scroll bar. If it looks good I'll revert those last few commits. |
Thanks @chrisj, that's great! And yes still much better for me when batched |
7317500 to
b3fd516
Compare
…s + segment property ui control + segment properties in invlerp control
segment_list: add prefetchBaseObjectColors - computes colors before rows are created add updateMany - recomputes colors for all currently rendered rows following display-state changes virtual_list: add optional VirtualListSource.prefetch(start, end) callback. It is called before missing rows in that interval are constructed
fc7512d to
775e56d
Compare
775e56d to
c4c7d9d
Compare
| toMerged: Uint32Array, | ||
| ): InlineSegmentNumericalProperty { | ||
| const values = new Float32Array(numMerged); | ||
| const values = property.values.slice(0, numMerged); |
There was a problem hiding this comment.
I've been diving into this change and need some thoughts.
This function is called when merging multiple segment property maps together. It was casting every numerical property values array to Float32Array. If the maps had differing sets of segments, each segment received a value of NaN for the numerical property of each map it was not in.
The easiest solution would be to just use a zero value and keep each values as it's original numerical type. Another option is to do that but add a validity mask. This is a rough idea of what that would look like: AllenInstitute@4e7a970
if (hasProp("myProperty")) {
uint value = prop("myProperty");
// use value
}I'm leaning towards using 0 instead of NaN for non-float and skipping the validity mask as I imagine it won't have much use.
There was a problem hiding this comment.
Seems reasonable to me to do the simpler version, I also can't imagine it's used too often
…segment properties, remove todo comments
Previously, merged numerical properties were initialized with NaN, which coerced integer typed arrays to zero while leaving float properties as NaN. Allocate the merged values with the source typed-array constructor so missing entries consistently default to zero, preserve the property datatype, and expand the bounds to include zero.
7dac20e to
1784f69
Compare
| ): InlineSegmentNumericalProperty { | ||
| const values = new Float32Array(numMerged); | ||
| values.fill(Number.NaN); | ||
| const values = new (property.values |

continuation of #862