Skip to content

Commit

Permalink
[performance] merge WebGL BufferAttribute update ranges before issuin…
Browse files Browse the repository at this point in the history
…g updates to the GPU (mrdoob#29189)

* sort update ranges before applying

* self review
  • Loading branch information
HunterLarco committed Sep 2, 2024
1 parent 6116e03 commit 08626b4
Showing 1 changed file with 44 additions and 0 deletions.
44 changes: 44 additions & 0 deletions src/renderers/webgl/WebGLAttributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,50 @@ function WebGLAttributes( gl ) {

if ( updateRanges.length !== 0 ) {

// Before applying update ranges, we merge any adjacent / overlapping
// ranges to reduce load on `gl.bufferSubData`. Empirically, this has led
// to performance improvements for applications which make heavy use of
// update ranges. Likely due to GPU command overhead.
//
// Note that to reduce garbage collection between frames, we merge the
// update ranges in-place. This is safe because this method will clear the
// update ranges once updated.

updateRanges.sort( ( a, b ) => a.start - b.start );

// To merge the update ranges in-place, we work from left to right in the
// existing updateRanges array, merging ranges. This may result in a final
// array which is smaller than the original. This index tracks the last
// index representing a merged range, any data after this index can be
// trimmed once the merge algorithm is completed.
let mergeIndex = 0;

for ( let i = 1; i < updateRanges.length; i ++ ) {

const previousRange = updateRanges[ mergeIndex ];
const range = updateRanges[ i ];

// We add one here to merge adjacent ranges. This is safe because ranges
// operate over positive integers.
if ( range.start <= previousRange.start + previousRange.count + 1 ) {

previousRange.count = Math.max(
previousRange.count,
range.start + range.count - previousRange.start
);

} else {

++ mergeIndex;
updateRanges[ mergeIndex ] = range;

}

}

// Trim the array to only contain the merged ranges.
updateRanges.length = mergeIndex + 1;

for ( let i = 0, l = updateRanges.length; i < l; i ++ ) {

const range = updateRanges[ i ];
Expand Down

0 comments on commit 08626b4

Please sign in to comment.