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

Parallel Worker Construction #627

Merged
merged 42 commits into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
81155e1
Small cleanup
gkjohnson Jan 26, 2024
2e469b5
Add worker base class
gkjohnson Jan 27, 2024
779d715
Some progress
gkjohnson Jan 27, 2024
c7ffe50
updates
gkjohnson Jan 27, 2024
533aee8
Merge remote-tracking branch 'origin' into parallel-construction
gkjohnson Jan 27, 2024
cc647d8
Simplify build functions
gkjohnson Jan 27, 2024
37b64b7
More simplification
gkjohnson Jan 27, 2024
6f9e927
More hashing out
gkjohnson Jan 27, 2024
4b52232
More updates
gkjohnson Jan 27, 2024
7641d49
Updates
gkjohnson Jan 27, 2024
d21310d
Cleanup
gkjohnson Jan 27, 2024
e50976b
Updates
gkjohnson Jan 27, 2024
a9c074b
Updates
gkjohnson Jan 27, 2024
977c981
Fixes
gkjohnson Jan 27, 2024
7271a77
Small fixes
gkjohnson Jan 28, 2024
a2d0621
Get it working
gkjohnson Jan 28, 2024
643c319
Small error
gkjohnson Jan 28, 2024
04da351
Small cleanup
gkjohnson Jan 28, 2024
9f88610
Get onProgress working
gkjohnson Jan 28, 2024
a3a465b
Lint updates
gkjohnson Jan 28, 2024
2c31699
Fix helper order
gkjohnson Jan 28, 2024
a684718
Update variable
gkjohnson Jan 28, 2024
85b1ece
Handle max depth case
gkjohnson Jan 28, 2024
bb886c0
Add null check
gkjohnson Jan 28, 2024
5c3f8b3
Update file names
gkjohnson Jan 28, 2024
bcd2d56
error update
gkjohnson Jan 28, 2024
b8feb82
Fixes
gkjohnson Jan 28, 2024
86f5599
Rearrange code
gkjohnson Jan 28, 2024
9ed3122
Remove copy of triangleBounds
gkjohnson Jan 28, 2024
03dcfbb
Remove unused import
gkjohnson Jan 28, 2024
dd45aa7
Bump parcel
gkjohnson Jan 28, 2024
519763a
Merge remote-tracking branch 'origin/master' into parallel-construction
gkjohnson Jan 29, 2024
f5e101d
Add support for parallel triangle bounds construction
gkjohnson Jan 29, 2024
fa060d8
comment
gkjohnson Jan 29, 2024
5ab2928
Update the async option
gkjohnson Jan 29, 2024
2097bf8
Add fallback
gkjohnson Jan 29, 2024
9eef8bf
Rearrange files
gkjohnson Jan 29, 2024
f8b54d1
Move more files
gkjohnson Jan 29, 2024
34f2d69
Update error message
gkjohnson Jan 29, 2024
02d6736
Error message update
gkjohnson Jan 29, 2024
a2233dd
Update async demo page
gkjohnson Jan 29, 2024
79edfd9
Update docs
gkjohnson Jan 29, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .proxyrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Proxy serve so SharedArrayBuffer works locally
export default function( app ) {

app.use( ( req, res, next ) => {

res.setHeader( 'Cross-Origin-Opener-Policy', 'same-origin' );
res.setHeader( 'Cross-Origin-Embedder-Policy', 'require-corp' );

next();

} );

}
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ geometry.boundsTree = deserializedBVH;

## Asynchronous Generation

_NOTE WebWorker syntax is inconsistently supported across bundlers and sometimes not supported at all so the GenerateMeshBVHWorker class is not exported from the package root. If needed the code from `src/worker` can be copied and modified to accomodate a particular build process._
_NOTE WebWorker syntax is inconsistently supported across bundlers and sometimes not supported at all so the GenerateMeshBVHWorker class is not exported from the package root. If needed the code from `src/worker` can be copied and modified to accommodate a particular build process._

```js
import { GenerateMeshBVHWorker } from 'three-mesh-bvh/src/workers/GenerateMeshBVHWorker.js';
Expand All @@ -201,6 +201,22 @@ worker.generate( geometry ).then( bvh => {
} );
```

_Parallel BVH generation is also supported using "ParallelMeshBVHWorker", which requires support for SharedArrayBuffer. If SharedArrayBuffer is not available it falls back to "GenerateMeshBVHWorker". It is recommended that geometry passed to this function have `position` and `index` with SharedArrayBuffer arrays, otherwise buffer copies must be made._

```js
import { ParallelMeshBVHWorker } from 'three-mesh-bvh/src/workers/ParallelMeshBVHWorker.js';

// ...

const geometry = new KnotBufferGeometry( 1, 0.5, 40, 10 );
const worker = new ParallelMeshBVHWorker();
worker.generate( geometry ).then( bvh => {

geometry.boundsTree = bvh;

} );
```

## BVH Queries in a Shader

See the shader implementation in the [simple GPU Path Tracing example](https://github.com/gkjohnson/three-mesh-bvh/blob/master/example/gpuPathTracingSimple.js) for an example on how to perform BVH ray queries in a shader. Or the [GPU SDF Generation example](https://github.com/gkjohnson/three-mesh-bvh/blob/master/example/sdfGeneration.js) for how to perform distance and closest point to point queries in a shader.
Expand Down
41 changes: 27 additions & 14 deletions example/asyncGenerate.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import * as THREE from 'three';
import Stats from 'stats.js';
import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js';
import { GenerateMeshBVHWorker } from '../src/workers/GenerateMeshBVHWorker.js';
import { acceleratedRaycast, MeshBVH, MeshBVHHelper } from '..';
import { ParallelMeshBVHWorker } from '../src/workers/ParallelMeshBVHWorker.js';
import { AVERAGE, CENTER, MeshBVH, MeshBVHHelper, SAH } from '..';

THREE.Mesh.raycast = acceleratedRaycast;
// Parallel BVH generation is only supported with SharedArrayBuffer
const sharedArrayBufferSupported = typeof SharedArrayBuffer !== 'undefined';

const params = {

useWebWorker: true,
maxWorkerCount: sharedArrayBufferSupported ? navigator.hardwareConcurrency : 1,
strategy: CENTER,

radius: 1,
tube: 0.3,
tubularSegments: 500,
Expand Down Expand Up @@ -86,7 +90,8 @@ function init() {

}

bvhGenerationWorker = new GenerateMeshBVHWorker();
bvhGenerationWorker = new ParallelMeshBVHWorker();
window.WORKER = bvhGenerationWorker;

gui = new GUI();
const helperFolder = gui.addFolder( 'helper' );
Expand All @@ -112,16 +117,21 @@ function init() {
helperFolder.open();

const knotFolder = gui.addFolder( 'knot' );
knotFolder.add( params, 'useWebWorker' );
knotFolder.add( params, 'radius', 0.5, 2, 0.01 );
knotFolder.add( params, 'tube', 0.2, 1.2, 0.01 );
knotFolder.add( params, 'tubularSegments', 50, 2000, 1 );
knotFolder.add( params, 'radialSegments', 5, 2000, 1 );
knotFolder.add( params, 'p', 1, 10, 1 );
knotFolder.add( params, 'q', 1, 10, 1 );
knotFolder.add( { regenerateKnot }, 'regenerateKnot' ).name( 'regenerate' );
knotFolder.open();

const bvhFolder = gui.addFolder( 'bvh' );
bvhFolder.add( params, 'useWebWorker' );
bvhFolder.add( params, 'maxWorkerCount', 1, 16, 1 ).disable( ! sharedArrayBufferSupported );
bvhFolder.add( params, 'strategy', { CENTER, AVERAGE, SAH } );

gui.add( { regenerateKnot }, 'regenerateKnot' ).name( 'regenerate' );

regenerateKnot();

window.addEventListener( 'resize', function () {
Expand Down Expand Up @@ -173,6 +183,7 @@ function regenerateKnot() {
);
const geomTime = window.performance.now() - geomStartTime;
const startTime = window.performance.now();
const options = { strategy: params.strategy };
let totalStallTime;
if ( params.useWebWorker ) {

Expand All @@ -185,7 +196,8 @@ function regenerateKnot() {

};

bvhGenerationWorker.generate( knot.geometry, { onProgress } ).then( bvh => {
bvhGenerationWorker.maxWorkerCount = params.maxWorkerCount;
bvhGenerationWorker.generate( knot.geometry, { onProgress, ...options } ).then( bvh => {

loadContainer.style.visibility = 'hidden';

Expand All @@ -207,17 +219,18 @@ function regenerateKnot() {
group.add( helper );

outputContainer.textContent =
`Geometry Generation Time : ${ geomTime.toFixed( 3 ) }ms\n` +
`BVH Generation Time : ${ deltaTime.toFixed( 3 ) }ms\n` +
`Frame Stall Time : ${ totalStallTime.toFixed( 3 ) }`;
`Geometry Generation Time : ${ geomTime.toFixed( 3 ) }ms\n` +
`BVH Generation Time : ${ deltaTime.toFixed( 3 ) }ms\n` +
`Frame Stall Time : ${ totalStallTime.toFixed( 3 ) }\n` +
`SharedArrayBuffer Support : ${ sharedArrayBufferSupported }`;

} );

totalStallTime = window.performance.now() - stallStartTime;

} else {

knot.geometry.boundsTree = new MeshBVH( knot.geometry );
knot.geometry.boundsTree = new MeshBVH( knot.geometry, options );
totalStallTime = window.performance.now() - stallStartTime;

group.add( knot );
Expand All @@ -231,9 +244,9 @@ function regenerateKnot() {
group.add( helper );

outputContainer.textContent =
`Geometry Generation Time : ${ geomTime.toFixed( 3 ) }ms\n` +
`BVH Generation Time : ${ deltaTime.toFixed( 3 ) }ms\n` +
`Frame Stall Time : ${ totalStallTime.toFixed( 3 ) }`;
`Geometry Generation Time : ${ geomTime.toFixed( 3 ) }ms\n` +
`BVH Generation Time : ${ deltaTime.toFixed( 3 ) }ms\n` +
`Frame Stall Time : ${ totalStallTime.toFixed( 3 ) }`;

}

Expand Down
Loading
Loading