Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebGPU module js build of Three.js #25947

Closed
andreasrosdal opened this issue Apr 27, 2023 · 57 comments
Closed

WebGPU module js build of Three.js #25947

andreasrosdal opened this issue Apr 27, 2023 · 57 comments
Assignees
Milestone

Comments

@andreasrosdal
Copy link
Contributor

Description

I would like a WebGPU build of Three.js in the /build directory. For example: three.webgpu.module.min.js
So that I can begin testing and implementing WebGPU support.

At the moment WebGL is hidden away in this directory:
https://github.com/mrdoob/three.js/blob/dev/examples/jsm/renderers/webgpu/WebGPURenderer.js

Solution

three.webgpu.module.min.js

Alternatives

Alternative: Include WebGPU in default module js build.

Additional context

No response

@Mugen87
Copy link
Collaborator

Mugen87 commented Apr 27, 2023

Um, what do you mean with "hidden away"? You can import the renderer like any other addon.

@andreasrosdal
Copy link
Contributor Author

The WebGPURenderer isn't included in the Three.js module js build. Instead it is stored in the /examples/jsm/renderers/webgpu/ subdirectory, and imports many other js files with specific relative paths.

So I wish that the WebGPU support with the WebGPURenderer was either included fully in the default module build of Three.js, or that there was a specific build of Three.js with WebGPU support.

@donmccurdy
Copy link
Collaborator

donmccurdy commented Apr 27, 2023

I don't think we should do anything immediately here, this approach is how many other important parts of three.js are packaged. But it would be worth planning a longer-term roadmap for WebGPU support; it will not be an addon forever.

@ghost
Copy link

ghost commented Apr 30, 2023

@andreasrosdal are you building using default vite or using own setup?
I'm asking because I'm experiencing issues building with vite (development version runs but production version is not).

Sorry for off-topic I'm relatively new to Threejs and WebGPU and want to verify that his is not an issue on my side.

@andreasrosdal
Copy link
Contributor Author

@rv4Flyver Fciv.net imports Three.js as a module directly, with a workaround. See the source code here: https://github.com/fciv-net/fciv-net/blob/main/freeciv-web/src/main/webapp/webclient/index.jsp#L58

The rest of the source code is built with Maven and Closure compiler.

I would like to use a more modern build system.

@makc
Copy link
Contributor

makc commented May 11, 2023

@andreasrosdal since you host the file yourself I dont see why cant you just build the version of 3js you want yourself? by editing this file and running standard 3js build, for example (this would not work because of circular dependency of three on itself).

@danrossi
Copy link

I've tried to look at this. Its referencing the module I create a custom build from sources as I found duplicates trying to reference the module when adding other imports.

The renderer tries to setup webgpu immediately with an async and not in the init method and patch Matrix4 in the init method. This breaks in an iife package. It needs to be setup in the init method.

@andreasrosdal
Copy link
Contributor Author

andreasrosdal commented May 22, 2023

I've tried to look at this. Its referencing the module I create a custom build from sources as I found duplicates trying to reference the module when adding other imports.

The renderer tries to setup webgpu immediately with an async and not in the init method and patch Matrix4 in the init method. This breaks in an iife package. It needs to be setup in the init method.

Cool, can you provide a WebGPU module build of Three.js?

@makc
Copy link
Contributor

makc commented May 22, 2023

@andreasrosdal why are you so lazy 🤣 but okay, try this js file:

import * as THREE from './three.gpu.js';
console.log(THREE);

three.gpu.js.zip

@makc
Copy link
Contributor

makc commented May 22, 2023

(all the Nodes.js stuff should be under THREE.Nodes)

@danrossi
Copy link

I'm working on figuring out how to make my custom three build as it references sources to stop duplicated imports that happens using the module. The code keeps making references to the module so might have to keep it that way. But there is refactoring required so it doesn't immediately setup webgpu. I may have to make a build of webgpu and reference my custom iife module build that includes custom components as global.

Here is refactoring snippets

patchApi() {

        Matrix4.prototype.makePerspective = makePerspective;
        Matrix4.prototype.makeOrthographic = makeOrthographic;
        Frustum.prototype.setFromProjectionMatrix = setFromProjectionMatrix;
        _frustum = new Frustum();
        _projScreenMatrix = new Matrix4();
        _vector3 = new Vector3();
    }

	async init() {

        if ( navigator.gpu !== undefined ) {

            staticAdapter = await navigator.gpu.requestAdapter();
        
        }

        this.patchApi();

Await when bundled causes an issue when trying to make a umd/iife bundle. Needs to be in init

 staticAdapter = await navigator.gpu.requestAdapter();

And then I can do

 if ( WebGPU.isAvailable()) {
                   renderer = new THREE.WebGPURenderer();
                   renderer.init();
                   console.log("using webgpu renderer");
               } else {
                   renderer = new THREE.WebGLRenderer();
               }

@danrossi
Copy link

danrossi commented May 23, 2023

Referencing the module to bundle the files, causes no files to be included and rollup just bundles the whole entire module. Its wierd. Only source includes works for me. But the webgpu files reference the module. I may have to fork that portion to use source includes also.

includePaths({
				paths: ["../three.js/src", "../three.js/examples/jsm"],
				include: {
				  'three': '../three.js/build/three.module.js'
				}
		  	}),

The WebGPU support tries to setup webgpu globally in the bundle. await breaks iife bundling. So support api check needs to be changed into a method.


if ( navigator.gpu !== undefined ) {

	const adapter = await navigator.gpu.requestAdapter();

	if ( adapter !== null ) {

		isAvailable = true;

	}

}

@makc
Copy link
Contributor

makc commented May 23, 2023

@danrossi

So support api check needs to be changed into a method.

why not just make a separate PR for this (separate from this issue, that is)

@danrossi
Copy link

danrossi commented May 23, 2023

Understood. I've setup this build project for now with the mods. I've got to test it still.

https://github.com/danrossi/three-webgpu-renderer/tree/master/build

The modded files

https://github.com/danrossi/three-webgpu-renderer/blob/master/src/renderers/webgpu/WebGPURenderer.js
https://github.com/danrossi/three-webgpu-renderer/blob/master/src/capabilities/WebGPU.js

@danrossi
Copy link

danrossi commented May 23, 2023

There is other problems I found. This gets bundled up with a tonne of stuff not needed normally for webglrenderer to support both and is run in the iife bundle but broken when compressing with terser. gets an error thrown. Should only be run when setting up the webgpurenderer if it needs it at all.

export function addNodeClass( nodeClass ) {

It's caused by a circular dependancy when trying to bundle it. Claims to not be a class when compressing because it has no class name.

(!) Circular dependency
three.js/examples/jsm/nodes/lighting/AnalyticLightNode.js -> three.js/examples/jsm/nodes/materials/MeshBasicNodeMaterial.js -> three.js/examples/jsm/nodes/materials/NodeMaterial.js -> three.js/examples/jsm/nodes/lighting/LightsNode.js -> three.js/examples/jsm/nodes/lighting/AnalyticLightNode.js

@danrossi
Copy link

I'm hoping that external project works. I did test it and realised I have to change alot of the integration, I use RawShaderMaterial with custom shader and it doesn't like that. I have to try and support both WebGLRenderer and WebGPURenderer. I may need to modify how the nodes are loaded. They all get initialized at once and may not all be needed or included. The bundle with WebGPU is 1.6mb compared to 600k. I'm looking at it once I can fix the WebXR polyfill as it seems threejs breaks it, not the other way.

@andreasrosdal
Copy link
Contributor Author

@danrossi Thank you for making this!
Is this build ready for me try test in www.Fciv.net?

What about Water2, Gltfimporter and other addons I use?

@sunag sunag self-assigned this May 30, 2023
@danrossi
Copy link

I haven't been able to properly test it yet outside the examples as stuff I use doesn't work with the renderer. There is a circular dependency bug that may prevent it working but import the built module and give it a try. The one bundled with three is huge, a 1.6mb bundle.

@andreasrosdal
Copy link
Contributor Author

I get this error:
Uncaught referenceError: GPUShaderStage is not defined

when using this build:
https://github.com/danrossi/three-webgpu-renderer/blob/master/build/three-webgpu.module.js

image
image

Can I please have just one js module build file? Why is there a webgpu-renderer.module.js

@mrdoob
Copy link
Owner

mrdoob commented May 31, 2023

@andreasrosdal What version of Chrome is that and what OS?

@andreasrosdal
Copy link
Contributor Author

Chromium Version 112 on OpenSUSE tumbleweed. I realize now that it doesn't support WebGPU yet. So I can try to use Google Chrome instead.

@sunag
Copy link
Collaborator

sunag commented May 31, 2023

/*
const gpuShaderStageLib = {
'vertex': GPUShaderStage.VERTEX,
'fragment': GPUShaderStage.FRAGMENT,
'compute': GPUShaderStage.COMPUTE
};
*/

This code snippet is currently deprecated, I think it would be nice to update the code, important updates have been made.

@mrdoob
Copy link
Owner

mrdoob commented May 31, 2023

Do we still need this?

if ( window.GPUShaderStage === undefined ) {
window.GPUShaderStage = { VERTEX: 1, FRAGMENT: 2, COMPUTE: 4 };
}

@sunag
Copy link
Collaborator

sunag commented May 31, 2023

Do we still need this?

Hmm... maybe not. I would just leave it until I make a GPU layout generation system, auto layout is limiting shadow integration.

@danrossi
Copy link

danrossi commented Jun 7, 2023

I'm looking back into the external module bundle as I believe WebGPU may be where we have to move to. However the bundle is huge I think and includes all the nodes one may not need. I'm going to figure something out to make it selective. The support check needs to be inside a method to await for a start where the api patch happens. So fallback support can be made for WebGLRenderer. The external async breaks in an iife bundle.

https://github.com/danrossi/three-webgpu-renderer/blob/master/src/renderers/webgpu/WebGPURenderer.js#L190

@marcofugaro
Copy link
Contributor

marcofugaro commented Jun 7, 2023

@danrossi can you share a project demo with your setup? The one making the iife bundle

@AdrianScott
Copy link

How do the webgpu examples on threejs.org work then? Shouldn't it be possible to create them as independent projects or something?

@mrdoob
Copy link
Owner

mrdoob commented Jul 6, 2023

@danrossi What's the current bundle size of a cube renderered using WebGPURenderer?

@danrossi
Copy link

danrossi commented Jul 6, 2023

The module minified with required node classes added to Terser exclusion is 209kb. with a full three build its 800kb. The loading of nodes should be selective somehow or selective exported in a module without having to copy files to override features. They all get registered on load of the page regardless if they are needed. It may slow page load.

https://github.com/danrossi/three-webgpu-renderer/blob/master/build/webgpu-renderer.module.min.js
https://github.com/danrossi/three-webgpu-renderer/blob/master/build/three-webgpu.min.js

with three 1.56MB

https://github.com/danrossi/three-webgpu-renderer/blob/master/build/three-webgpu.module.js

832kb minified

https://github.com/danrossi/three-webgpu-renderer/blob/master/build/three-webgpu.module.min.js

I have it bundled in a troika build project. But I can't use it yet until the video texture performance issue is corrected.

A selective three build bundle is 1.23MB

https://github.com/danrossi/three-troika/blob/main/build/three/three.module.js
https://github.com/danrossi/three-troika/blob/main/threelib.js

The very end bundle package is an iife. Why I have to make a copy of the gpubackend with my fix. Although that usage code again is within another iife package. end user only has to include the script on the page and configure things for the application I built with it. Its for a webcam video grid to merge webrtc conferencing streams to one stream with graphical elements. And then webrtc publish that canvas stream with audio mixed in an audio destination. Most people out there demonstrate canvas software rendering. Each video texture added adds resources so was hoping to test webgpu.

Expecting modules and imports to setup things is difficult for end users with variable technical abilities and the imported code is usually done internally to set things up. I have to deal with devs and non devs.

https://github.com/danrossi/three-troika/blob/main/test/index.html

@mrdoob
Copy link
Owner

mrdoob commented Jul 6, 2023

The module minified with required node classes added to Terser exclusion is 209kb.

Nice! Is that gzipped?

@danrossi
Copy link

danrossi commented Jul 6, 2023

The module minified with required node classes added to Terser exclusion is 209kb.

Nice! Is that gzipped?

It's just terser minified. I can try a zipped option. When deploying to s3 in my build scripts I gzip files while uploading.

@danrossi
Copy link

danrossi commented Jul 6, 2023

The file minified then compressed with zopfli is 55kb. and 200kb for the three bundle. Are these importable served gzipped ? I don't know how to test the gzip yet.

https://github.com/danrossi/three-webgpu-renderer/blob/master/build/webgpu-renderer.module.min.js.gz
https://github.com/danrossi/three-webgpu-renderer/blob/master/build/three-webgpu.module.min.js.gz

@mrdoob
Copy link
Owner

mrdoob commented Jul 12, 2023

If you have a terminal you can do gzip bundle.js and it will produce a bundle.js.gz.

@danrossi
Copy link

I have a zopfli compression build in rollup. That produces those files above. I mean it has to be setup to be served with the correct mimetype.

@andreasrosdal
Copy link
Contributor Author

Great work on this WebGPU build. Is this build now in such a working state that I can begin using this?

@danrossi
Copy link

You can fork and do whatever you like with it as long as the submodule is updated during the build. One thing to note they are still adding materials. Not all materials support is there yet and I don't know enough to add them myself. You can make a ticket to request maybe.

But in my version I have to make a duplicated version of the backend so it can work in iife bundles and I have to merge changes each time.

https://github.com/danrossi/three-webgpu-renderer/blob/master/src/renderers/webgpu/WebGPUBackend.js

Which is still the most common bundle for applications. I cant release my stuff as modules personally as I deal with people of variable technical abilities. I made a PR to fix the top level async issue as webgpu will be requested when loading the module before even checking for webgpu support to fallback to WebGL so a logical issue. but it seems its not accepted and people are going to be forced to release applications as modules.

I haven't had the time to figure out how to bundle as a module and work like iife with a namespace yet. I'm on rebuilding a legacy XR polyfill for Iphone with a stereo distortion effect.

There is still performance issues with video textures. The cpu issue has been fixed and now consumes 1-2% cpu but it now consumes 20-40% gpu for video textures. It requires digging through each call stage to figure out why.

https://danrossi.github.io/three-webgpu-renderer/tests/webgpu_video_panorama_equirectangular.html

@mrdoob
Copy link
Owner

mrdoob commented Jul 25, 2023

The file minified then compressed with zopfli is 55kb. and 200kb for the three bundle.

Why are there two files? Aren't we trying to produce a single build?

@danrossi
Copy link

There is a bundle with just the renderer module. And one with three built into it if anyone needs it. An example project that takes the module in via npm. Although I can't activate it yet until a performance problem is fixed.

https://github.com/danrossi/three-troika/blob/main/package.json#L20

@AdrianScott
Copy link

Thanks for all of the help, Dan, and Mr Doob and team for Three.js. We were able to get this published onto the Bitcoin blockchain. Looks like it's the first Ordinals/NFT collection using WebGPU, built on top of Three.js and the work of many great folks: https://ordinals.com/content/7dbc067eb7a692c9811cbff25b23ef82b4329cbcc2b729d05f493db887a19744i0

(hit 'm' to start the spatial audio, lots of other keys do things; more info https://twitter.com/Anarkoic/status/1684370030060769282 )

We basically did a build using Dan Rossi's three-gpu-renderer repo, but had to use a really limited subset of three.js, e.g. basic materials etc. Need to get around to writing it up a bit more. Cheers.

@danrossi
Copy link

It's ok not a problem. Just avoid video textures with webgpu and fallback to webgl for now. I tried my best very to pin point the high gpu usage problem. Where the issue I discovered is binding a group, I don't understand how it's different to the vanilla code.

@andreasrosdal
Copy link
Contributor Author

Thanks for this great effort in making a WebGPU build of Three.js.

Can three-webgpu-renderer please be updated to the latest Three.js version?

Is it perhaps time now to get a official build of Three.js with WebGPU support in the Three.js repo?

Thank you!

@andreasrosdal
Copy link
Contributor Author

One official build of Three.js with support for both WebGPU and WebGL 2 would be ideal.

@danrossi
Copy link

I'm sorry mate it's mine. You can fork and run the build yourself. I try to check in and keep it up to date. But to be absolutely honest I am personally having issues finding regular customers right now and issues at home to keep up with this.

So an automatic build matching my rollup config might be more useful I guess. I found I had to export ALL the nodes exports to be useful for using with the node system. All those math and shader method exports. I am slowly trying to figure out the node system myself and is hard figuring out the vertex part trying to replicate a third party shader I am force to migrate myself. Taking ages.

@danrossi
Copy link

danrossi commented Nov 17, 2023

done. I might have accidently committed a node system test I am working on.

@danrossi
Copy link

Something has been reverted so now have high gpu usage with video textures again I have to report.

@andreasrosdal
Copy link
Contributor Author

andreasrosdal commented Nov 17, 2023

Bugreport in this WebGPU renderer:

  1. When the game becomes too complex after ca. 20 turns it will crash. Error: [Invalid RenderPipeline] is invalid.
    image

  2. Error: NodeMaterial: Material "ShaderMaterial" is not compatible. This error comes all the time.
    image

@danrossi
Copy link

You can't use ShaderMaterial with WebGPU you have to use the nodes system to design your shader or using wgsl directly. For me the nodes system is universal for both. Just still trying to figure it out.

You can see what I was trying to work on here, it's still tests. I can only get the fragment manipulated properly for now. https://github.com/danrossi/three-webgpu-renderer/blob/master/tests/webgpu_nodes.html

@andreasrosdal
Copy link
Contributor Author

The ShaderMaterial error (bug 2 above) was solved for now by not using ShaderMaterial.

However, bug 1 above is still happening. It can be reproduced here, start a game, and when the game becomes "complex" (many units and cities), it will crash. https://www.fciv.net/?webgpu=true

error: no matching constructor for vec4(vec4, f32)

283911157-c04534c1-1de0-4ec2-9241-636375f088da

@danrossi
Copy link

You are using the three bundle build. I added the correct exports to import vec4 for your node system to that bundle I am only working on the other bundle right now. Report problems here danrossi/three-webgpu-renderer#6

@andreasrosdal
Copy link
Contributor Author

There is a great WebGPU build of Three.js here:
https://github.com/danrossi/three-webgpu-renderer

Maybe it is time now for official WebGPU builds of Three.js so we can always get up-to-date builds. Thank you!

@danrossi
Copy link

danrossi commented Jan 7, 2024

I was tied up with upgrades of my conferencing project. I've updated the builds.

@Mugen87
Copy link
Collaborator

Mugen87 commented Jun 30, 2024

Fixed via #28650.

@Mugen87 Mugen87 closed this as completed Jun 30, 2024
@Mugen87 Mugen87 added this to the r167 milestone Jun 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants