11import { AdjacencyMatrix } from '../../AdjacencyMatrix' ;
22import { BufferData } from '../../BufferData' ;
3- import type { Edge , Graph , Node } from '../../AdjacencyList' ;
3+ import type { Edge , Graph } from '../../AdjacencyList' ;
44import type { Path } from '../../path' ;
55import { mapAndReadBuffer } from '../../utils' ;
66import shader from './shader.wgsl?raw' ;
7- import { writeGPUBuffer } from '../../GPUBuffer' ;
7+ import { createGPUBuffer , writeGPUBuffer } from '../../GPUBuffer' ;
88
99export type FloydWarshallParams = {
1010 graph : Graph ;
@@ -31,6 +31,9 @@ export class FloydWarshall {
3131 #uniformsBufferData: BufferData < { k : 'uint' ; edge_weight_factor : 'float' } > ;
3232 #uniformsBuffer: GPUBuffer | undefined ;
3333
34+ #pathsBufferData: BufferData < { start : 'uint' ; end : 'uint' } > | undefined ;
35+ #pathsBuffer: GPUBuffer | undefined ;
36+
3437 constructor ( { graph, device, edgeWeightFactor = 1 } : FloydWarshallParams ) {
3538 this . graph = graph ;
3639 this . #device = device ;
@@ -131,7 +134,7 @@ export class FloydWarshall {
131134 } ) ;
132135 }
133136
134- async compute ( ) {
137+ async compute ( readBack = false ) {
135138 for ( let k = 0 ; k < this . distanceMatrix . size ; ++ k ) {
136139 this . #uniformsBufferData. set ( { k } ) ;
137140
@@ -157,59 +160,63 @@ export class FloydWarshall {
157160 this . #device. queue . submit ( [ commandBuffer ] ) ;
158161 }
159162
160- const encoder = this . #device. createCommandEncoder ( { label : 'compute builtin encoder' } ) ;
161- encoder . copyBufferToBuffer (
162- this . #distanceMatrixBuffer! ,
163- 0 ,
164- this . #distanceMatrixReadBuffer! ,
165- 0 ,
166- this . distanceMatrix . buffer . byteLength
167- ) ;
163+ if ( readBack ) {
164+ const encoder = this . #device. createCommandEncoder ( { label : 'compute builtin encoder' } ) ;
165+ encoder . copyBufferToBuffer (
166+ this . #distanceMatrixBuffer! ,
167+ 0 ,
168+ this . #distanceMatrixReadBuffer! ,
169+ 0 ,
170+ this . distanceMatrix . buffer . byteLength
171+ ) ;
168172
169- encoder . copyBufferToBuffer (
170- this . #nextMatrixBuffer! ,
171- 0 ,
172- this . #nextMatrixReadBuffer! ,
173- 0 ,
174- this . nextMatrix . buffer . byteLength
175- ) ;
173+ encoder . copyBufferToBuffer (
174+ this . #nextMatrixBuffer! ,
175+ 0 ,
176+ this . #nextMatrixReadBuffer! ,
177+ 0 ,
178+ this . nextMatrix . buffer . byteLength
179+ ) ;
176180
177- const commandBuffer = encoder . finish ( ) ;
178- this . #device. queue . submit ( [ commandBuffer ] ) ;
181+ const commandBuffer = encoder . finish ( ) ;
182+ this . #device. queue . submit ( [ commandBuffer ] ) ;
179183
180- await this . #distanceMatrixReadBuffer! . mapAsync ( GPUMapMode . READ ) ;
181- const distances = new Float32Array ( await this . #distanceMatrixReadBuffer! . getMappedRange ( ) ) ;
184+ await this . #distanceMatrixReadBuffer! . mapAsync ( GPUMapMode . READ ) ;
185+ const distances = new Float32Array ( await this . #distanceMatrixReadBuffer! . getMappedRange ( ) ) ;
182186
183- await this . #nextMatrixReadBuffer! . mapAsync ( GPUMapMode . READ ) ;
184- const next = new Uint32Array ( await this . #nextMatrixReadBuffer! . getMappedRange ( ) ) ;
185- this . distanceMatrix . values = distances ;
186- this . nextMatrix . values = next ;
187+ await this . #nextMatrixReadBuffer! . mapAsync ( GPUMapMode . READ ) ;
188+ const next = new Uint32Array ( await this . #nextMatrixReadBuffer! . getMappedRange ( ) ) ;
189+ this . distanceMatrix . values = distances ;
190+ this . nextMatrix . values = next ;
191+ }
187192 }
188193
189194 async shortestPaths ( paths : { start : number ; end : number } [ ] ) : Promise < ( Path | null ) [ ] > {
190195 console . time ( 'Shortest Paths Buffer Data' ) ;
191- const pathsBufferData = new BufferData (
192- {
193- start : 'uint' ,
194- end : 'uint' ,
195- } ,
196- paths . length
197- ) ;
196+ if ( ! this . #pathsBufferData) {
197+ this . #pathsBufferData = new BufferData (
198+ {
199+ start : 'uint' ,
200+ end : 'uint' ,
201+ } ,
202+ paths . length
203+ ) ;
198204
199- for ( let i = 0 ; i < paths . length ; i ++ ) {
200- const { start, end } = paths [ i ] ! ;
201- pathsBufferData . set ( { start, end } , i ) ;
205+ for ( let i = 0 ; i < paths . length ; i ++ ) {
206+ const { start, end } = paths [ i ] ! ;
207+ this . #pathsBufferData. set ( { start, end } , i ) ;
208+ }
202209 }
203210 console . timeEnd ( 'Shortest Paths Buffer Data' ) ;
204211
205212 console . time ( 'Shortest Paths Buffer Compute' ) ;
206- const pathsBuffer = this . #device . createBuffer ( {
207- label : 'Paths Buffer' ,
208- size : pathsBufferData . buffer . byteLength ,
209- usage : GPUBufferUsage . STORAGE | GPUBufferUsage . COPY_SRC | GPUBufferUsage . COPY_DST ,
210- } ) ;
211-
212- this . #device . queue . writeBuffer ( pathsBuffer , 0 , pathsBufferData . buffer ) ;
213+ if ( ! this . #pathsBuffer ) {
214+ this . #pathsBuffer = createGPUBuffer ( {
215+ device : this . #device ,
216+ data : this . #pathsBufferData ,
217+ usage : GPUBufferUsage . STORAGE | GPUBufferUsage . COPY_SRC | GPUBufferUsage . COPY_DST ,
218+ } ) ;
219+ }
213220
214221 const shortestPathsDistancesBuffer = this . #device. createBuffer ( {
215222 size : paths . length * 4 ,
@@ -249,7 +256,7 @@ export class FloydWarshall {
249256 entries : [
250257 { binding : 0 , resource : { buffer : this . #distanceMatrixBuffer! } } ,
251258 { binding : 1 , resource : { buffer : this . #nextMatrixBuffer! } } ,
252- { binding : 3 , resource : { buffer : pathsBuffer } } ,
259+ { binding : 3 , resource : { buffer : this . # pathsBuffer! } } ,
253260 { binding : 4 , resource : { buffer : shortestPathsDistancesBuffer } } ,
254261 { binding : 5 , resource : { buffer : shortestPathsNodesBuffer } } ,
255262 ] ,
@@ -296,7 +303,7 @@ export class FloydWarshall {
296303 const ret : ( Path | null ) [ ] = [ ] ;
297304
298305 for ( let i = 0 ; i < paths . length ; i ++ ) {
299- const endIndex = pathsBufferData . get ( 'end' , i ) [ 0 ] ! ;
306+ const endIndex = this . # pathsBufferData. get ( 'end' , i ) [ 0 ] ! ;
300307
301308 const nodes : number [ ] = [ ] ;
302309
@@ -316,4 +323,13 @@ export class FloydWarshall {
316323
317324 return ret ;
318325 }
326+
327+ set edgeWeightFactor ( value : number ) {
328+ this . #uniformsBufferData. set ( { edge_weight_factor : value } ) ;
329+ writeGPUBuffer ( {
330+ device : this . #device,
331+ buffer : this . #uniformsBuffer! ,
332+ data : this . #uniformsBufferData,
333+ } ) ;
334+ }
319335}
0 commit comments