@@ -74,15 +74,14 @@ export const getBitonicDisperseIndices = /*@__PURE__*/ Fn( ( [ index, swapSpan ]
7474 ]
7575} ) ;
7676
77- // TODO: Add parameters for computing a buffer larger than vec4
7877export class BitonicSort {
7978
8079 /**
8180 * Constructs a new light probe helper.
8281 *
8382 * @param {Renderer } renderer - The current scene's renderer.
84- * @param {StorageBufferNode } [size=1] - The size of the helper .
85- * @param {Object } [options={}] - The size of the helper .
83+ * @param {StorageBufferNode } dataBuffer - The data buffer to sort .
84+ * @param {Object } [options={}] - Options that modify the bitonic sort .
8685 */
8786 constructor ( renderer , dataBuffer , options = { } ) {
8887
@@ -167,18 +166,31 @@ export class BitonicSort {
167166 this . stepCount = this . _getStepCount ( ) ;
168167
169168 /**
170- * A compute shader that executes a 'flip' swap within a global address space on elements in the data buffer .
169+ * The number of the buffer being read from .
171170 *
172- * @type {ComputeNode }
171+ * @type {string }
173172 */
174- this . flipGlobalFn = this . _getFlipGlobal ( ) ;
173+ this . readBufferName = 'Data' ;
175174
176175 /**
177- * A compute shader that executes a 'disperse ' swap within a global address space on elements in the data buffer.
176+ * An object containing compute shaders that execute a 'flip ' swap within a global address space on elements in the data buffer.
178177 *
179- * @type {ComputeNode }
178+ * @type {Object<string, ComputeNode> }
179+ */
180+ this . flipGlobalNodes = {
181+ 'Data' : this . _getFlipGlobal ( this . dataBuffer , this . tempBuffer ) ,
182+ 'Temp' : this . _getFlipGlobal ( this . tempBuffer , this . dataBuffer )
183+ } ;
184+
185+ /**
186+ * An object containing compute shaders that execute a 'disperse' swap within a global address space on elements in the data buffer.
187+ *
188+ * @type {Object<string, ComputeNode> }
180189 */
181- this . disperseGlobalFn = this . _getDisperseGlobal ( ) ;
190+ this . disperseGlobalNodes = {
191+ 'Data' : this . _getDisperseGlobal ( this . dataBuffer , this . tempBuffer ) ,
192+ 'Temp' : this . _getDisperseGlobal ( this . tempBuffer , this . dataBuffer )
193+ } ;
182194
183195 /**
184196 * A compute shader that executes a sequence of flip and disperse swaps within a local address space on elements in the data buffer.
@@ -190,9 +202,12 @@ export class BitonicSort {
190202 /**
191203 * A compute shader that executes a sequence of disperse swaps within a local address space on elements in the data buffer.
192204 *
193- * @type {ComputeNode }
205+ * @type {Object<string, ComputeNode> }
194206 */
195- this . disperseLocalFn = this . _getDisperseLocal ( ) ;
207+ this . disperseLocalNodes = {
208+ 'Data' : this . _getDisperseLocal ( this . dataBuffer ) ,
209+ 'Temp' : this . _getDisperseLocal ( this . tempBuffer ) ,
210+ } ;
196211
197212 // Utility functions
198213
@@ -248,6 +263,7 @@ export class BitonicSort {
248263 * Get total number of distinct swaps that occur in a bitonic sort.
249264 *
250265 * @private
266+ * @returns {number } - The total number of distinct swaps in a bitonic sort
251267 */
252268 _getSwapOpCount ( ) {
253269
@@ -260,6 +276,7 @@ export class BitonicSort {
260276 * Get the number of steps it takes to execute a complete bitonic sort.
261277 *
262278 * @private
279+ * @returns {number } The number of steps it takes to execute a complete bitonic sort.
263280 */
264281 _getStepCount ( ) {
265282
@@ -292,8 +309,12 @@ export class BitonicSort {
292309
293310 /**
294311 * Compares and swaps two data points in the data buffer within the global address space.
295- *
312+ * @param {Node<uint> } idxBefore - The index of the first data element in the data buffer.
313+ * @param {Node<uint> } idxAfter - The index of the second data element in the data buffer.
314+ * @param {StorageBufferNode } dataBuffer - The buffer of data to read from.
315+ * @param {StorageBufferNode } tempBuffer - The buffer of data to write to.
296316 * @private
317+ *
297318 */
298319 _globalCompareAndSwapTSL ( idxBefore , idxAfter , dataBuffer , tempBuffer ) {
299320
@@ -309,6 +330,8 @@ export class BitonicSort {
309330 * Compares and swaps two data points in the data buffer within the local address space.
310331 *
311332 * @private
333+ * @param {Node<uint> } idxBefore - The index of the first data element in the data buffer.
334+ * @param {Node<uint> } idxAfter - The index of the second data element in the data buffer
312335 */
313336 _localCompareAndSwapTSL ( idxBefore , idxAfter ) {
314337
@@ -327,17 +350,20 @@ export class BitonicSort {
327350 * Create the compute shader that performs a global disperse swap on the data buffer.
328351 *
329352 * @private
353+ * @param {StorageBufferNode } readBuffer - The data buffer to read from.
354+ * @param {StorageBufferNode } writeBuffer - The data buffer to read from.
355+ * @returns {ComputeNode } - A compute shader that performs a global disperse swap on the data buffer.
330356 */
331- _getDisperseGlobal ( ) {
357+ _getDisperseGlobal ( readBuffer , writeBuffer ) {
332358
333- const { infoStorage, tempBuffer , dataBuffer } = this ;
359+ const { infoStorage } = this ;
334360
335361 const currentSwapSpan = infoStorage . element ( 1 ) ;
336362
337363 const fnDef = Fn ( ( ) => {
338364
339365 const idx = getBitonicDisperseIndices ( instanceIndex , currentSwapSpan ) ;
340- this . _globalCompareAndSwapTSL ( idx . x , idx . y , dataBuffer , tempBuffer ) ;
366+ this . _globalCompareAndSwapTSL ( idx . x , idx . y , readBuffer , writeBuffer ) ;
341367
342368 } ) ( ) . compute ( this . dispatchSize , [ this . workgroupSize ] ) ;
343369
@@ -349,17 +375,20 @@ export class BitonicSort {
349375 * Create the compute shader that performs a global flip swap on the data buffer.
350376 *
351377 * @private
378+ * @param {StorageBufferNode } readBuffer - The data buffer to read from.
379+ * @param {StorageBufferNode } writeBuffer - The data buffer to read from.
380+ * @returns {ComputeNode } - A compute shader that executes a global flip swap.
352381 */
353- _getFlipGlobal ( ) {
382+ _getFlipGlobal ( readBuffer , writeBuffer ) {
354383
355- const { infoStorage, tempBuffer , dataBuffer } = this ;
384+ const { infoStorage } = this ;
356385
357386 const currentSwapSpan = infoStorage . element ( 1 ) ;
358387
359388 const fnDef = Fn ( ( ) => {
360389
361390 const idx = getBitonicFlipIndices ( instanceIndex , currentSwapSpan ) ;
362- this . _globalCompareAndSwapTSL ( idx . x , idx . y , dataBuffer , tempBuffer ) ;
391+ this . _globalCompareAndSwapTSL ( idx . x , idx . y , readBuffer , writeBuffer ) ;
363392
364393 } ) ( ) . compute ( this . dispatchSize , [ this . workgroupSize ] ) ;
365394
@@ -372,6 +401,7 @@ export class BitonicSort {
372401 * Create the compute shader that performs a complete local swap on the data buffer.
373402 *
374403 * @private
404+ * @returns {ComputeNode } - A compute shader that executes a full local swap.
375405 */
376406 _getSwapLocal ( ) {
377407
@@ -440,10 +470,12 @@ export class BitonicSort {
440470 * Create the compute shader that performs a local disperse swap on the data buffer.
441471 *
442472 * @private
473+ * @param {StorageBufferNode } readWriteBuffer - The data buffer to read from and write to.
474+ * @returns {ComputeNode } - A compute shader that executes a local disperse swap.
443475 */
444- _getDisperseLocal ( ) {
476+ _getDisperseLocal ( readWriteBuffer ) {
445477
446- const { localStorage, dataBuffer , workgroupSize } = this ;
478+ const { localStorage, workgroupSize } = this ;
447479
448480 const fnDef = Fn ( ( ) => {
449481
@@ -454,8 +486,8 @@ export class BitonicSort {
454486 const localID1 = invocationLocalIndex . mul ( 2 ) ;
455487 const localID2 = invocationLocalIndex . mul ( 2 ) . add ( 1 ) ;
456488
457- localStorage . element ( localID1 ) . assign ( dataBuffer . element ( localOffset . add ( localID1 ) ) ) ;
458- localStorage . element ( localID2 ) . assign ( dataBuffer . element ( localOffset . add ( localID2 ) ) ) ;
489+ localStorage . element ( localID1 ) . assign ( readWriteBuffer . element ( localOffset . add ( localID1 ) ) ) ;
490+ localStorage . element ( localID2 ) . assign ( readWriteBuffer . element ( localOffset . add ( localID2 ) ) ) ;
459491
460492 // Ensure that all local data has been populated
461493 workgroupBarrier ( ) ;
@@ -477,8 +509,8 @@ export class BitonicSort {
477509 // Ensure that all invocations have swapped their own regions of data
478510 workgroupBarrier ( ) ;
479511
480- dataBuffer . element ( localOffset . add ( localID1 ) ) . assign ( localStorage . element ( localID1 ) ) ;
481- dataBuffer . element ( localOffset . add ( localID2 ) ) . assign ( localStorage . element ( localID2 ) ) ;
512+ readWriteBuffer . element ( localOffset . add ( localID1 ) ) . assign ( localStorage . element ( localID1 ) ) ;
513+ readWriteBuffer . element ( localOffset . add ( localID2 ) ) . assign ( localStorage . element ( localID2 ) ) ;
482514
483515 } ) ( ) . compute ( this . dispatchSize , [ this . workgroupSize ] ) ;
484516
@@ -490,6 +522,7 @@ export class BitonicSort {
490522 * Create the compute shader that resets the sort's algorithm information.
491523 *
492524 * @private
525+ * @returns {ComputeNode } - A compute shader that resets the bitonic sort's algorithm information.
493526 */
494527 _getResetFn ( ) {
495528
@@ -512,9 +545,10 @@ export class BitonicSort {
512545 }
513546
514547 /**
515- * Create the compute shader that copies the state of the global swap to the data buffer.
548+ * Create the compute shader that copies the state of the last global swap to the data buffer.
516549 *
517550 * @private
551+ * @returns {ComputeNode } - A compute shader that copies the state of the last global swap to the data buffer.
518552 */
519553 _getAlignFn ( ) {
520554
@@ -533,9 +567,10 @@ export class BitonicSort {
533567 }
534568
535569 /**
536- * Create the compute shader that sets the algorithm's information.
570+ * Create the compute shader that sets the bitonic sort algorithm's information.
537571 *
538572 * @private
573+ * @returns {ComputeNode } - A compute shader that sets the bitonic sort algorithm's information.
539574 */
540575 _getSetAlgoFn ( ) {
541576
@@ -603,15 +638,24 @@ export class BitonicSort {
603638
604639 const swapType = this . globalOpsRemaining === this . globalOpsInSpan ? 'Flip' : 'Disperse' ;
605640
606- await renderer . computeAsync ( swapType === 'Flip' ? this . flipGlobalFn : this . disperseGlobalFn ) ;
607- await renderer . computeAsync ( this . alignFn ) ;
641+ await renderer . computeAsync ( swapType === 'Flip' ? this . flipGlobalNodes [ this . readBufferName ] : this . disperseGlobalNodes [ this . readBufferName ] ) ;
642+
643+ if ( this . readBufferName === 'Data' ) {
644+
645+ this . readBufferName = 'Temp' ;
646+
647+ } else {
648+
649+ this . readBufferName = 'Data' ;
650+
651+ }
608652
609653 this . globalOpsRemaining -= 1 ;
610654
611655 } else {
612656
613657 // Then run local disperses when we've finished all global swaps
614- await renderer . computeAsync ( this . disperseLocalFn ) ;
658+ await renderer . computeAsync ( this . disperseLocalNodes [ this . readBufferName ] ) ;
615659
616660 const nextSpanGlobalOps = this . globalOpsInSpan + 1 ;
617661 this . globalOpsInSpan = nextSpanGlobalOps ;
@@ -624,6 +668,15 @@ export class BitonicSort {
624668
625669 if ( this . currentDispatch === this . stepCount ) {
626670
671+ // If our last swap addressed only addressed the temp buffer, then re-allign it with the data buffer
672+ // to fulfill the requirement of an in-place sort.
673+ if ( this . readBufferName === 'Temp' ) {
674+
675+ await renderer . computeAsync ( this . alignFn ) ;
676+ this . readBufferName = 'Data' ;
677+
678+ }
679+
627680 // Just reset the algorithm information
628681 await renderer . computeAsync ( this . resetFn ) ;
629682
0 commit comments