Conversation
08e9db7 to
34b5fa3
Compare
9223ca5 to
f22e9a4
Compare
Extract WebGPU code from AlignmentsRenderer into WebGPUAlignmentsRenderer, making AlignmentsRenderer a thin facade that selects between WebGPU, WebGL, and Canvas2D backends via a shared AlignmentsBackend interface. Move RenderState and upload data types into rendererTypes.ts, eliminating the Parameters<WebGLRenderer[...]> indirection and Canvas2D→WebGL type coupling. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the dual glFallback/canvas2dFallback fields with a single fallback field in wiggle, hic, canvas, synteny, dotplot, variant, LD, and variant matrix renderers. This matches the pattern established in the alignments renderer refactoring. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Consolidate duplicated createShader, createProgram, splitPositionWithFrac, and cacheUniforms functions from 6 separate copies across wiggle, hic, variants, alignments, canvas, sequence, dotplot, and synteny plugins into a single shared module in packages/core. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix effectiveShowDescriptions to respect config default (was only checking raw trackShowDescriptions override). Fix handleMouseMove empty-data branch missing featureIdUnderMouse cleanup. Remove unnecessary double cast on colorByCDS since LGV already has the property. Extract regionKeys getter to deduplicate computation, use useEffectEvent for renderWithBlocks instead of useCallback+ref, extract hitTestAtEvent/clearHoverState helpers, flatten selectFeatureById, consolidate preProcessSnapshot destructuring. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract WebGPU code from mixed facade/backend classes into dedicated WebGPU*Renderer files implementing shared *Backend interfaces. Each renderer system now follows the same pattern: a facade class handles the fallback chain (WebGPU → WebGL → Canvas2D) and delegates to a backend interface, matching the architecture established in alignments. Affected plugins: linear-comparative-view (synteny), dotplot-view, variants (VariantMatrix, Variant, LD), hic, canvas (features), wiggle. Also normalizes destroy() → dispose() across all backends, fixes method name mismatches (uploadForRegion → uploadRegion, pruneStaleRegions → pruneRegions), removes unnecessary null checks on constructor- guaranteed fields, and adds Canvas2D renderer tests for dotplot and hic. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove more unnecessary useEffects - GroupByDialog: move state clearing to onChange handler - ImportForm: replace useEffect sync with derived value pattern (userValue ?? r0) - RegionWidthEditorDialog: remove dead useEffect (dialog opens fresh each time) - Loading: fix missing [] deps (timer was resetting every render) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Fix spreadsheet NumberEditor: call model setter when clamping to 1 When user enters 0 or negative, the display resets to 1 but the model setter was not being called, unlike the original useEffect-based code. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Fix lint warnings in AddConnectionWidget/ConnectionTypeSelect - Remove unused ConnectionType import - Remove unnecessary optional chains and conditionals now that connectionType is always defined - Tighten setConnectionType callback type from optional to required Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use color-bits directly in GPU hot paths, add colorBits re-export - Add @jbrowse/core/util/colorBits module re-exporting color-bits with helpers for named CSS color support (parseCssColor, cssColorToNormalizedRgb, cssColorToRgba, cssColorToNormalizedRgba) - Update 11 GPU rendering files to import from colorBits directly, bypassing the colord wrapper object allocation - Remove unused colord dependency from @jbrowse/plugin-wiggle Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Add tests for colord wrapper and colorBits helpers Tests cover parsing (hex, named colors, rgb/hsl strings, transparent, case insensitivity), formatting (toHex, toRgbString, toHslString), manipulation (alpha, darken, lighten, mix), and the direct colorBits helper functions (cssColorToNormalizedRgb, cssColorToRgba, etc). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Fix unused variable lint error in colorBits test Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Remove unnecessary conditionals in AddConnectionWidget configModel is always truthy since it comes from useMemo calling configSchema.create(), so the conditional checks were redundant. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The reversed field was being dropped in mergedVisibleRegions and
bufferedVisibleRegions, causing horizontally flipped views to render
with wrong strand orientation. Also fixes DisplayedRegionsChange
autorun not detecting flip changes (missing reversed in comparison key).
Introduces RegionWithNumber type and flattens the { region, regionNumber }
nesting throughout the fetch pipeline, removing gratuitous wrapping/
unwrapping across all display plugins.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All RPC renameRegionsIfNeeded methods manually reconstructed region objects, dropping reversed (and any other extra fields). Use spread from the renamed result instead, which preserves all fields since the core renameRegionIfNeeded already spreads. Also adds reversed to RenderPileupDataArgs type and updates the integration test to use RegionWithNumber. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The reversed flag was only used for strand arrow direction but not for the actual x-positioning of features. When a region is horizontally flipped, lower bp should appear on the right and higher bp on the left. Adds a reversed field to FeatureRenderBlock and implements coordinate flipping in all three rendering backends: - WebGL: u_reversed uniform negates clip-space X via mix() - WebGPU: same approach in WGSL hp_to_clip_x - Canvas2D: mirrors bpToScreenX from screenEndPx instead of screenStartPx Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…lipX Negating inside hpToClipX broke the min-width check (sx2 - sx1 goes negative when reversed, collapsing all rects to 1px). Instead, keep hpToClipX unmodified and apply flipX() on the final gl_Position.x / out.position.x. This preserves all intermediate math (min-width, snapping, chevron spacing) while correctly mirroring the output. Also fixes JavaScript-side bp-to-px conversions for floating labels, amino acid overlays, and hit detection via a shared bpToScreenPx helper that handles reversed regions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The shader's flipX() handles all spatial mirroring for reversed regions. The RPC layer was also computing effectiveStrand (negating strand when reversed), which caused a double-flip — arrows, chevrons, and amino acids stayed in their original positions instead of mirroring. Now the RPC layer uses raw strand for all direction and position calculations. getStrandArrowPadding no longer takes a reversed param. Child layout offset calculations no longer flip for reversed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add flip_x() to all GLSL/WGSL shaders (reads, CIGAR, coverage, arcs, connecting lines) across WebGL, WebGPU, and Canvas2D backends. Pass reversed flag from view regions through RenderBlock to each renderer. Fix hit testing coordinate conversion to account for reversed regions so mouse hover/click resolves to the correct genomic position. Remove reversed from displayed-regions-change comparison so flipping a region doesn't trigger a data re-fetch and visual blank. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move duplicated high-precision position shader snippets (HP_WGSL_CORE, HP_GLSL_CORE) to a single source of truth in core. Canvas and variant plugins now import from core instead of defining inline copies. Standardize GLSL HP function names to snake_case to match WGSL convention. Fix broken Canvas2D constant import names (HEAD_HALF_H_PX_PX, etc). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add flip_x() to GLSL/WGSL shaders and pass reversed flag through RenderBlock for LinearWiggleDisplay, MultiLinearWiggleDisplay, and MultiVariantDisplay across WebGL, WebGPU, and Canvas2D backends. Fix hit testing coordinate conversion in both plugins to account for reversed regions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pull non-graph/non-MultiLGVSyntenyDisplay changes from the webgl-poc-multisyn branch: - Remove baseUrl from all tsconfig.build.esm.json files - Bump dependency versions (@mui/x-data-grid, dockview, storybook, typescript 6.0.2, eslint, canvas, sanitize-filename, etc.) - Remove react-refresh webpack plugin and add hot:false to dev server - Remove d3-hierarchy2 vendored code from variants plugin, replaced by @jbrowse/tree-sidebar package - Remove MultiLGVSyntenyDisplay and MultiSyntenyTrack from linear-comparative-view (these belong on the multisyn branch) - Add FLIP_GLSL export to alignments shaders/utils.ts - Add test/data and *.log to .gitignore and eslint ignore - Update root package.json: remove react-refresh, add serve-static Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…debar Replace inline hierarchy/cluster code and TreeSidebar component with shared @jbrowse/tree-sidebar package. Fix renderSvg color parameter naming (posColor/negColor) and add renderSvgColors test. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The RPC layer still uses clusterData/toNewick from @gmod/hclust directly. The dynamic import of treeDrawingAutorun now points to @jbrowse/tree-sidebar. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
bufferedVisibleRegions returns flat objects with regionNumber as a
top-level property alongside refName/start/end/assemblyName. Update
all onFetchNeeded signatures and destructuring to match this flat
format instead of expecting a nested { region, regionNumber } wrapper.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Export RegionWithNumber = Region & { regionNumber: number } from
MultiRegionDisplayMixin. Use this alias in onFetchNeeded,
withFetchLifecycle, and computeAndSetArcs signatures across
alignments, canvas, and linear-genome-view plugins.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Simplify computeAndSetArcs to push flat RegionWithNumber directly instead of extracting .region properties. Pass mergedVisibleRegions directly to computeAndSetArcs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…DisplayModel import - Add missing reversed field when constructing RenderBlock objects in alignments and canvas plugins - Import WiggleDisplayModel type so it's in scope for the component prop Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… $nonEmptyObject leak
Spreading MST snapshot objects carries the $nonEmptyObject symbol into
inferred return types, causing TS4058 declaration emit errors. Switch
RegionWithNumber from a flat intersection (Region & { regionNumber })
to a nested interface { region: Region; regionNumber: number } that
keeps the plain Region separate from the metadata.
Update all consumers: bufferedVisibleRegions, onFetchNeeded,
withFetchLifecycle, computeAndSetArcs, wiggle fetch helpers, and tests.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
# Conflicts: # .github/workflows/push.yml # .gitignore # package.json # packages/core/src/util/io/RemoteFileWithRangeCache.ts # plugins/alignments/src/LinearPileupDisplay/SharedLinearPileupDisplayMixin.ts # plugins/alignments/src/LinearPileupDisplay/components/GroupByDialog.test.tsx # plugins/alignments/src/LinearPileupDisplay/model.ts # plugins/alignments/src/LinearSNPCoverageDisplay/model.ts # plugins/wiggle/src/shared/SharedWiggleMixin.ts # plugins/wiggle/src/util.ts # pnpm-lock.yaml # products/jbrowse-web/browser-tests/__snapshots__/alignments-bam.png # products/jbrowse-web/browser-tests/__snapshots__/alignments-volvox-sv.png # products/jbrowse-web/browser-tests/__snapshots__/breakpoint_split_view_snapshot.png # products/jbrowse-web/browser-tests/__snapshots__/main-thread-rpc-bam.png # products/jbrowse-web/browser-tests/__snapshots__/methylation_snapshot.png # products/jbrowse-web/browser-tests/__snapshots__/session-spec-display-snapshot-type.png # products/jbrowse-web/browser-tests/__snapshots__/workspaces-add-view.png # products/jbrowse-web/browser-tests/__snapshots__/workspaces-layout-custom-sizes.png # products/jbrowse-web/browser-tests/__snapshots__/workspaces-layout-url-param.png # products/jbrowse-web/browser-tests/__snapshots__/workspaces-new-tab.png # products/jbrowse-web/browser-tests/__snapshots__/workspaces-split-view.png # products/jbrowse-web/browser-tests/runner.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
JBrowse (both 1 and 2) have been "optimized for side scrolling". The "static blocks" based methodology reflects this: tiles of data are prerendered side by side. However this is not really the most important type of scrolling! Smooth zoom is arguably more important!
In order to get true smooth zooming, we likely need to adopt webgl. The reason webgl is needed is that we can provide all the "coordinate data" to the webgl renderer, and the GPU just does transformations on zoom level changes or side scroll. Contrast this with canvas, where on zoom level change, we have to completely, on the CPU, re-draw everything with javascript
This is something that can not be done smoothly via canvas. Every single frame needs redrawing. The only "hacky" way to incorporate it into canvas is just applying canvas 'transforms' which distorts. We also see this in our current code with the css 'scaleX' which also distorts
We have to think quite seriously to try to overcome our limitations and get to true smooth scrolling...and that likely requires webgl
I don't know a lot about webgl and there may be some hard challenges to come up against, but this is a very early demonstration of what it might look like to use webgl for the alignments track.
Possible challenges
There are many possible challenges, that range from known challenges to unknown challenges.
Some challenges i currently forsee include:
My current thinking is to try to make this just apply on a track by track basis. This means that there might be many webgl contexts on a single screen. This actually is somewhat dangerous because browsers limit the number of webgl contexts that are available. WebGL only allows 16 contexts at a time. However, it is hard to even have 16 tracks open at once. I think that if we combine this with IntersectionObserver, we will be able to make it work 99% of the time. We can consider looking into things like https://github.com/greggman/virtual-webgl
It may be challenging to make our code work with our web worker architecture. There is the concept of web workers rendering to main thread canvases, but our current web worker code renders a static bitmap, sends that result to main thread. We don't dynamically control it on a per-frame basis. Furthermore, it is known that serializing too much data between the main thread and webworker is also very slow, so we can't just get automatic gains by parsing on the web worker and serializing drawing to the main thread. This demo is just main thread only.
There may some clients that have browser compat issues with webgl. We may need canvas fallback
Our svg export will need to have a custom mapping as we use the fact that we rendered to canvas as a mechanism to serialize those canvas commands to svg. that drawing code will need to be persistently probably maintained separately, which isn't very fun, but extreme unit testing might help cover here
Video
This video demo should be compelling to anyone who has ever zoomed in or out in jbrowse. It simply demonstrates smooth zooming. Compare against master where the entire screen blanks and re-renders at each zoom level, and the smooth zoom feels much more natural
out.mp4
Share link
this likely still has glitches and weirdness. only bam files on the alignments track are demonstrated for the time
you can use "mouse wheel vertical scroll" in the area of the bam track to scroll zoom
https://jbrowse.org/code/jb2/webgl-poc/?config=test_data%2Fvolvox%2Fconfig.json&session=share-1eTgCoKkSa&password=x4Byl
Context
This was motivated by work with Pratik on the lorax project https://lorax.ucsc.edu/ this project is deeply webgl driven and is interested in integrating with jbrowse (meeting with Pratik later this week)
Caveats
This PR is very hackily implemented, and largely claude coded. It is unclear if we will run into any blockers, however, even seeing some amount of progress i hope helps to see that it could be quite compelling to implement this