Skip to content

feature: WebGPU Rendering Enhancements#256

Draft
Jarbuckle wants to merge 38 commits into
mainfrom
joel/DT-9482-webgpu-scatterbrain-updates
Draft

feature: WebGPU Rendering Enhancements#256
Jarbuckle wants to merge 38 commits into
mainfrom
joel/DT-9482-webgpu-scatterbrain-updates

Conversation

@Jarbuckle
Copy link
Copy Markdown
Contributor

@Jarbuckle Jarbuckle commented May 11, 2026

feature: WebGPU Rendering Enhancements

What

In support of the Connectomics initiative, we are making updates to Vis to enable WebGPU rendering -- initially for the Scatterbrain package, but not limited to that package. WebGPU rendering will allow us to render to multiple canvases, as well as situating Vis for long-term support of modern web technologies.

This PR is focused on building reusable systems to simplify the process of defining and using WebGPU rendering pipelines. It will be an ongoing draft PR until we have settled on the systems that we want (R&D process).

How

  • Built programmatic wrappers around shader elements to make building shaders a modular and reusable system.
  • MORE TBD

PR Checklist

  • Is your PR title following our conventional commit naming recommendations?
  • Have you filled in the PR Description Template?
  • Is your branch up to date with the latest in main?
  • Do the CI checks pass successfully?
  • Have you smoke tested the example applications?
  • Did you check that the changes meet accessibility standards?
  • Have you tested the application on these browsers?
    • Chrome (Fully supported)
    • Firefox (Major bug fixes supported)
    • Safari (Major bug fixes supported)

froyo-np and others added 30 commits April 22, 2026 12:10
…ain (to bring it into connectomics quickly...) experimental, might try typeGPU again
…with the webGPU stuff (startlight cant build wgpu-utils, site/ cant resolve webGPU types)
thinking through how to make better use of how webGPU works with regard to the nice way of thinking via REGL.
@Jarbuckle Jarbuckle changed the title WebGPU Updates for Scatterbrain WebGPU Rendering Enhancements May 12, 2026
@Jarbuckle Jarbuckle changed the title WebGPU Rendering Enhancements feature: WebGPU Rendering Enhancements May 12, 2026

import type { Declaration } from "./declarations";

export class WGSLShader {
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.

still reading through all this - so far I like a lot of it!

my first thought here though is that I dont think this being a class is helpful!
why not type WGSLShader = Declaration[] ?

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.

It all comes down to preference, I guess 😅 I like to think of shaders (in their final form) as a definite thing, not just raw data.

}

serialize(): string {
return JSON.stringify(this.#definition);
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.

if this class was instead an open type - then its users could do their own serialization in whatever form they wanted

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.

True, but they could also extend the class and override the functions that way. Again, I think it all comes down to expectations and mental models; there is no functional difference, in my mind, between the model you're proposing and the one in the code currently.

this.#definition = { declarations };
}

static deserialize(serialized: string): WGSLShader {
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.

this is just asking for runtime errors imho

Copy link
Copy Markdown
Contributor Author

@Jarbuckle Jarbuckle May 14, 2026

Choose a reason for hiding this comment

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

Curious which runtime errors you're thinking are most likely? Deserialization failures? Or issues with the shader not being a valid shader? Or something else?

}

asSource(): string {
return this.#definition.declarations.map((d) => d.__gen()).join(';\n');
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.

this is the only useful part of this class - could easily be
function asWgslSource(declaration[]) { ... }

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.

True; personally, I prefer the .asSource() call, since to me at least it presents a clearer entity model for my mental map of the interface.

highlightValue: number;
} & QuantitativeFilterRanges;

export const applyCamera = func(
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 like a bunch of the other constructed wrappers, but I'm not so sure about the func constructor. it feels less ergonomic then just the literal wgsl string you'd use - and because its internal to a shader, its not really buying us much in terms of type safety is it? functions defined this way still get invoked in raw WGSL

Copy link
Copy Markdown
Collaborator

@froyo-np froyo-np May 13, 2026

Choose a reason for hiding this comment

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

I'm not saying get rid of it - but what if Declaration had an escape hatch member type to allow a literal blob of WGSL?

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.

Does it need to be internal to a shader, though? 🤔 The goal behind this was to provide a way of making function declarations reusable across shaders; allowing for a simple "chunk of WGSL" approach feels much less encapsulated (and I do love me some encapsulation, since it sets expectations -- crucial for the programmer-program interface, in my mind).

vsOutputStruct,
uniform('unis', uniformStruct.name, 0, 0),
texture(categoricalTable, 'texture_2d<f32>', 0, 1),
texture(gradientTable, 'texture_2d<f32>', 0, 2),
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.

this part I do like - its clear to see the structure of the things in the 'header' of the shader are generated, and because the gross part of constructing them is done elsewhere, this is a nice concise reading of the interface to the shader from outside.

rangeParameter,
within,
constant('clip', /*wgsl*/ `array<vec2f,4>(vec2f(1, -1), vec2f(1, 1), vec2f(-1, -1), vec2f(-1, 1))`),
vertexEntry(
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.

here again - I think the preamble to the vertex main fn in raw wgsl is much more legible than this:
@vertex fn vmain(v:Vertex)->VsOutput

Copy link
Copy Markdown
Contributor Author

@Jarbuckle Jarbuckle May 14, 2026

Choose a reason for hiding this comment

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

With that, I do agree. Part of the lack of legibility is due to Oxfmt's default formatting rules (insisting on having parameters on separate lines -- not really helping in this case), but yes, it's more readable in raw WGSL.


export function param(
name: string,
type: string,
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.

might be nice to constrain this more - perhaps (if its a structDeclaration) we could pull the .name out so the person authoring these doesnt have to

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.

Yeah, having the type be able to specifically reference a previously-defined struct would be a nice addition, agreed.

};
}

export function member(name: string, type: string, attributes?: VariableOrValueAttribute[]): StructMemberDeclaration {
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.

because the type parameter here is just a raw string, and I dont have syntax highlighting because I'm not writing raw WGSL , I feel like this is a step backward in type-safeness, right?

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.

It is, for sure. Per my response above, making this able to handle pre-defined types seems like a definite improvement.

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.

2 participants